当前位置: 首页 > news >正文

【网络编程】C++实现网络通信服务器程序||计算机网络课设||Linux系统编程||TCP协议(附源码)

0000

TCP网络服务器

  • 🐍 1.程序简洁
  • 🦎2. 服务端ServerTcp程序介绍
  • 🦖3.线程池ThreadPool介绍
  • 🦕 4.任务类Task介绍
  • 🐙5. 客户端Client介绍
  • 🦑6.运行结果:
  • 🦐 7. 源码
    • 🦞7.1 serverTcp.cc
    • 🦀 7.2 ThreadPool.hpp
    • 🐡7.3 Task.hpp
    • 🐠7.4ClientTcp.cc
    • 🐟 7.5 Lock.hpp
    • 🐬7.7头文件util.hpp
    • 🐳7.6Makefile 文件
    • 🐋7.8 日志文件 log.hpp

🐍 1.程序简洁

该程序用C++实现了一个支持并发的服务器,实现了大小写转换的功能,当客户端向服务器发起链接请求时,服务器响应请求,分配资源处理任务,实现大小写的转换功能,用到的相关技术栈有:C++编程、socket套接字编程、线程池等。

🦎2. 服务端ServerTcp程序介绍

0001

在ServerTcp函数定义定义了一个init函数,用于配置服务器的网络监听套接字,绑定IP地址和端口,并开始监听来自客户端的连接请求。
①首先创建套接字:
使用 函数创建一个套接字,这里使用的是IPv4()和TCP()协议。如果创建失败,会记录错误信息并退出程序。socketPF_INETSOCK_STREAM
②绑定地址和端口:
创建一个 结构体变量 ,它用于保存服务器的本地地址信息。struct sockaddr_inlocal
2.2. 清空 结构体,然后设置其成员变量,包括地址族(,设为 表示IPv4)、端口号(,通过 将主机字节序转换为网络字节序)、IP地址(),IP地址可以是配置的服务器IP或者通配地址 。localsin_familyPF_INETsin_porthtonssin_addr.s_addrINADDR_ANY
2.3. 使用 函数将创建的套接字 与上述配置绑定。如果绑定失败,会记录错误信息并退出程序。bindlistenSock_
③监听套接字:
使用 函数将套接字设置为监听状态,同时指定了允许等待连接的队列长度为5。如果监听失败,会记录错误信息并退出程序。listen
④加载线程池:
在这里,代码通过 获取了一个线程池的单例对象,用于处理客户端的请求。这个线程池的类型是 ,这是一个自定义的任务类,它将在客户端连接时调用来处理请求。ThreadPool::getInstance()Task
最后的注释解释了程序运行到这一步时,服务器已经配置完成,等待客户端的连接请求。

0002

这段代码是服务器的主循环函数 ,它是服务器的核心部分,用于不断接受客户端的连接请求,然后将连接的处理任务交给线程池来执行。
①打开线程池:
使用 启动线程池。这个操作会让线程池中的线程开始运行,并等待任务的到来。tp_->start()
②记录线程池启动成功的日志:
使用 记录一个 DEBUG 级别的日志,表示线程池启动成功,同时记录线程池中线程的数量。
③主循环:
进入一个无限循环,用于不断接受客户端的连接请求。
④接受连接:
使用 函数等待客户端的连接请求,当有客户端连接时, 返回一个新的套接字 ,用于与客户端通信。
⑤处理连接失败:
如果 返回的套接字小于 0,表示连接失败,代码记录一个 WARNING 级别的日志,包含错误信息,然后继续等待下一个连接请求。
⑥获取客户端信息:
6.1. 获取客户端的端口号和IP地址,并进行字节序的转换,以便后续日志记录和任务处理。
6.2. 记录 DEBUG 级别的日志,表示接受到客户端的连接请求,同时包含连接信息和套接字文件描述符。
创建任务对象:
在这里,代码创建了一个 Task对象 ,这个对象用于包装客户端的套接字、IP地址、端口号以及服务处理的回调函数 。
⑦将任务加入线程池:
使用 tp_->push(t);将任务 添加到线程池中等待执行。然后不断循环

🦖3.线程池ThreadPool介绍

0004

该代码实现了一个简单的线程池类,当创建线程池实例时,调用start函数之后会创建15个线程(预先设定),当有任务通过push接口进入任务队列时,线程会执行threadRountine()函数,首先该判断该线程任务队列里有没有任务在执行,如果有,那就进行条件等待 void waitForTask() { pthread_cond_wait(&cond_, &mutex_); } ,线程池里支持15个线程同时执行处理任务的函数,当任务数超过15时才会出现等待,实现了多线程并发提高了任务执行效率.

🦕 4.任务类Task介绍

0005

‘Task’ 类的主要作用是将任务与处理该任务的函数关联起来,使任务的处理变得可定制化。当线程池从任务队列中取出任务时,会调用 ‘Task’ 对象的 ‘operator()’ 函数,进而执行与任务关联的回调函数,完成任务的处理。这种方式允许灵活地定义和执行不同类型的任务。

🐙5. 客户端Client介绍

0006

这是一个简单的客户端程序,用于与服务器建立连接并进行通信。
首先要判断运行客户端的方式必须是 接收3个参数 运行程序+ip+端口
然后绑定协议族等信息,把接收的参数封装起来,与远端的服务器发起链接请求,进行通信,当输入的内容为”quit”时退出客户端.

🦑6.运行结果:

0007

🦐 7. 源码

🦞7.1 serverTcp.cc

#include "util.hpp"
#include <signal.h>
#include <sys/types.h>
#include <sys/wait.h>
#include"Threadpool.hpp"
#include <pthread.h>
#include"Task.hpp"//服务函数  ---->>>小写转换大写void transService(int sock,const std::string &clientip,uint16_t clientPort){assert(sock >= 0);assert(!clientip.empty());assert(clientPort >= 1024);char inbuffer[BUFFER_SIZE];while (true){ssize_t s=read(sock,inbuffer,sizeof(inbuffer)-1); //给“\0”留一个位置if(s>0){//读取成功inbuffer[s]='\0';if(strcasecmp(inbuffer,"quit")==0){//如果输入quit直接退出logMessage(DEBUG, "client quit -- %s[%d]", clientip.c_str(), clientPort);break;}logMessage(DEBUG,"trans before: %s[%d]>>>%s",clientip.c_str(),clientPort,inbuffer);//下面进行大小写转换 for(int i = 0; i < s; i++){if(isalpha(inbuffer[i]) && islower(inbuffer[i])) inbuffer[i] = toupper(inbuffer[i]);}logMessage(DEBUG, "trans after: %s[%d]>>> %s", clientip.c_str(), clientPort, inbuffer);//把转换后的写回套接字write(sock, inbuffer, strlen(inbuffer));}else if (s == 0){logMessage(DEBUG, "client quit -- %s[%d]", clientip.c_str(), clientPort);break;}else{logMessage(DEBUG, "%s[%d] - read: %s", clientip.c_str(), clientPort, strerror(errno));break;}}// 只要走到这里,一定是client退出了,服务到此结束close(sock); // 如果一个进程对应的文件fd,打开了没有被归还,文件描述符泄漏!logMessage(DEBUG, "server close %d done", sock);}template<class T>
class ServerTcp; // 申明一下ServerTcp
template<class T>
class ThreadData
{
public:uint16_t clientPort_;std::string clinetIp_;int sock_;ServerTcp <T>*this_;
public:ThreadData(uint16_t port, std::string ip, int sock,  ServerTcp<T> *ts): clientPort_(port), clinetIp_(ip), sock_(sock),this_(ts){}
};
template<class T>
class ServerTcp
{public://构造ServerTcp(uint16_t port,const std::string &ip=""):port_(port),ip_(ip),listenSock_(-1),tp_(nullptr){}//析构~ServerTcp(){}public:void init() //初始化函数{//1.创建套接字listenSock_=socket(PF_INET,SOCK_STREAM,0);   //PF_INET=IPV4 SOCK_STREAM=TCP 最后一个参数是协议 默认是0if (listenSock_ < 0) //如果socket创建成功会返回一个非负整数{//创建失败logMessage(FATAL, "socket: %s", strerror(errno));exit(SOCKET_ERR);}logMessage(DEBUG, "socket: %s, %d", strerror(errno), listenSock_);//2.bind绑定//2.1填充服务器信息struct sockaddr_in local; // 用户栈memset(&local, 0, sizeof local);local.sin_family = PF_INET;//ipv4local.sin_port = htons(port_);//htons 主机字节序转网络字节序ip_.empty()?(local.sin_addr.s_addr=INADDR_ANY):(inet_aton(ip_.c_str(),&local.sin_addr));//2.2本地socket信息 写入socket_t对应区域 if(bind(listenSock_,(const struct sockaddr*)&local,sizeof local)<0){logMessage(FATAL,"bind:%s",strerror(errno));exit(BIND_ERR);}logMessage(DEBUG,"bind:%s,%d",strerror(errno),listenSock_);//3.监听套接字 if(listen(listenSock_,5)<0){logMessage(FATAL,"listen:%s",strerror(errno));exit(LISTEN_ERR);}logMessage(DEBUG,"listen:%s,%d",strerror(errno),listenSock_);//加载线程池tp_=ThreadPool<Task>::getInstance();//获取单例//到这一步就运行起来等待客户端链接...}//多线程static void *threadRoutine(void *args){pthread_detach(pthread_self()); //设置线程分离ThreadData<T> *td = static_cast<ThreadData<T>*>(args);td->this_->transService(td->sock_, td->clinetIp_, td->clientPort_);delete td;return nullptr;}void loop(){   //打开线程池 初始化tp_->start();logMessage(DEBUG, "thread pool start success, thread num: %d", tp_->threadNum());while(true){struct sockaddr_in peer;socklen_t len=sizeof(peer);//4.获取链接int serviceSock=accept(listenSock_,(struct sockaddr* )&peer,&len);if(serviceSock<0){//获取链接失败logMessage(WARINING,"Accept :%s[%d]",strerror(errno),serviceSock);continue;//获取失败继续获取}//4.1获取客户端基本信息uint16_t peerPort = ntohs(peer.sin_port);std::string peerIp = inet_ntoa(peer.sin_addr);logMessage(DEBUG, "accept: %s | %s[%d], socket fd: %d",strerror(errno), peerIp.c_str(), peerPort, serviceSock);//5 提供服务, echo -> 小写 -> 大写//5.0 v0 版本 -- 单进程 -- 一旦进入transService,主执行流,就无法进行向后执行,只能提供完毕服务之后才能进行accept//transService(serviceSock, peerIp, peerPort);//多线版本// ThreadData *td = new ThreadData(peerPort, peerIp, serviceSock, this);// pthread_t tid;// pthread_create(&tid, nullptr, threadRoutine, (void*)td);//线程池Task t(serviceSock, peerIp, peerPort, transService);tp_->push(t);}}private:// sockint listenSock_;// portuint16_t port_;// ipstd::string ip_;// 引入线程池ThreadPool<Task> *tp_;
};static void Usage(std::string proc)
{std::cerr << "Usage:\n\t" << proc << " port ip" << std::endl;std::cerr << "example:\n\t" << proc << " 8080 127.0.0.1\n" << std::endl;}// ./ServerTcp local_port local_ip
int main(int argc, char *argv[])
{if(argc != 2 && argc != 3 ){//只能提供两个或者三个参数Usage(argv[0]);exit(USAGE_ERR);}uint16_t port = atoi(argv[1]);std::string ip;if(argc == 3) ip = argv[2];ServerTcp<Task> svr(port, ip);svr.init();svr.loop();return 0;
}

🦀 7.2 ThreadPool.hpp

#pragma once#include <iostream>
#include <cassert>
#include <queue>
#include <memory>
#include <cstdlib>
#include <pthread.h>
#include <unistd.h>
#include <sys/prctl.h>
#include "Lock.hpp"
using namespace std;int gThreadNum = 15; // 线程数
template <class T>
class ThreadPool
{
private:ThreadPool(int threadNum = gThreadNum) : threadNum_(threadNum), isStart_(false){assert(threadNum_ > 0);pthread_mutex_init(&mutex_, nullptr);pthread_cond_init(&cond_, nullptr);}// 禁止掉拷贝构造和赋值构造ThreadPool(const ThreadPool<T> &) = delete;void operator=(const ThreadPool<T> &) = delete;public:static ThreadPool<T> *getInstance(){static Mutex mutex;if (nullptr == instance) // 检查是否已经存在单例对象 (第一次检查){LockGuard LockGuard(&mutex); // 进入代码块 加锁 退出if (nullptr == instance)     // (第二次检查){instance = new ThreadPool<T>();}/*首先在没有锁的情况下检查一次instance是否为空,然后在加锁的情况下再进行一次检查确保多线程情况之下,只有一个线程成功创建实例*/}return instance;}// 线程执行函数static void *threadRountine(void *args){/*每个线程将在该函数中循环等待任务,获取任务,执行任务,然后再次等待*/pthread_detach(pthread_self()); // 线程分离  防止资源泄漏ThreadPool<T> *tp = static_cast<ThreadPool<T> *>(args);while (1){tp->lockQueue();while (!tp->haveTask()){tp->waitForTask();}// 拿到任务T t = tp->pop();tp->unlockQueue();t();}}void start(){assert(!isStart_);for (int i = 0; i < threadNum_; i++){pthread_t temp;pthread_create(&temp, nullptr, threadRountine, this); // 创建线程}isStart_ = true; // 修改状态}void push(const T &in){lockQueue();taskQueue_.push(in);choiceThreadForHandler();unlockQueue();}~ThreadPool(){pthread_mutex_destroy(&mutex_);pthread_cond_destroy(&cond_);}int threadNum(){return threadNum_;}private:void lockQueue(){pthread_mutex_lock(&mutex_);} // 加锁void unlockQueue() { pthread_mutex_unlock(&mutex_); }          // 解锁bool haveTask() { return !taskQueue_.empty(); }                // 判断有没有任务在执行void waitForTask() { pthread_cond_wait(&cond_, &mutex_); }     // 条件等待void choiceThreadForHandler() { pthread_cond_signal(&cond_); } // 唤醒等待T pop(){T temp = taskQueue_.front();taskQueue_.pop();return temp;}private:bool isStart_;int threadNum_;queue<T> taskQueue_;    // 任务队列pthread_mutex_t mutex_; // 锁pthread_cond_t cond_;   // 条件变量/*条件标志的作用是在一个或多个线程等待某个条件成立的情况下,阻塞自己,直到其他线程改变了共享数据并发出信号告诉等待的线程可以继续执行*/static ThreadPool<T> *instance; // 设置单例// const static int a = 100;
};
template <class T>
ThreadPool<T> *ThreadPool<T>::instance = nullptr;

🐡7.3 Task.hpp

#pragma once#include <iostream>
#include <string>
#include <functional>
#include <pthread.h>
#include "log.hpp"class Task
{
public://等价于// typedef std::function<void (int, std::string, uint16_t)> callback_t;using callback_t = std::function<void (int, std::string, uint16_t)>;
private:int sock_; // 给用户提供IO服务的sockuint16_t port_;  // client portstd::string ip_; // client ipcallback_t func_;  // 回调方法
public:Task():sock_(-1), port_(-1){}Task(int sock, std::string ip, uint16_t port, callback_t func): sock_(sock), ip_(ip), port_(port), func_(func){}void operator () (){logMessage(DEBUG, "线程ID[%p]处理%s:%d的请求 开始啦...",\pthread_self(), ip_.c_str(), port_);func_(sock_, ip_, port_);logMessage(DEBUG, "线程ID[%p]处理%s:%d的请求 结束啦...",\pthread_self(), ip_.c_str(), port_);}~Task(){}
};

🐠7.4ClientTcp.cc

#include "util.hpp"
// 2. 需要bind吗??需要,但是不需要自己显示的bind! 不要自己bind!!!!
// 3. 需要listen吗?不需要的!
// 4. 需要accept吗?不需要的!volatile bool quit = false;static void Usage(std::string proc)
{std::cerr << "Usage:\n\t" << proc << " serverIp serverPort" << std::endl;std::cerr << "Example:\n\t" << proc << " 127.0.0.1 8081\n"<< std::endl;
}
// ./clientTcp serverIp serverPort
int main(int argc, char *argv[])
{if (argc != 3){Usage(argv[0]);exit(USAGE_ERR);}std::string serverIp = argv[1];uint16_t serverPort = atoi(argv[2]);// 1. 创建socket SOCK_STREAMint sock = socket(AF_INET, SOCK_STREAM, 0);if (sock < 0){std::cerr << "socket: " << strerror(errno) << std::endl;exit(SOCKET_ERR);}// 2. connect,向服务器发起链接请求, // 2.1 先填充需要连接的远端主机的基本信息struct sockaddr_in server;memset(&server, 0, sizeof(server));server.sin_family = AF_INET;server.sin_port = htons(serverPort);inet_aton(serverIp.c_str(), &server.sin_addr);// 2.2 发起请求,connect 会自动帮我们进行bind!if (connect(sock, (const struct sockaddr *)&server, sizeof(server)) != 0){std::cerr << "connect: " << strerror(errno) << std::endl;exit(CONN_ERR);}std::cout << "info : connect success: " << sock << std::endl;std::string message;while (!quit){message.clear();std::cout << "请输入你的消息>>> ";std::getline(std::cin, message); // 结尾不会有\nif (strcasecmp(message.c_str(), "quit") == 0)quit = true;ssize_t s = write(sock, message.c_str(), message.size());if (s > 0){message.resize(1024);ssize_t s = read(sock, (char *)(message.c_str()), 1024);if (s > 0)message[s] = 0;std::cout << "Server Echo>>> " << message << std::endl;}else if (s <= 0){break;}}close(sock);return 0;
}

🐟 7.5 Lock.hpp

本程序暂不涉及临界资源的访问 互斥锁的机制 可加可不加 我这里加上了 是为了学习和使用。

#pragma once
#include<iostream>
#include<pthread.h>
class Mutex
{public:Mutex(){pthread_mutex_init(&lock_,nullptr);}~Mutex(){pthread_mutex_destroy(&lock_);}void lock(){pthread_mutex_lock(&lock_);}void unlock(){pthread_mutex_unlock(&lock_);}private:pthread_mutex_t lock_;
};class LockGuard
{
public:LockGuard(Mutex *mutex) : mutex_(mutex){mutex_->lock();std::cout << "加锁成功..." << std::endl;}~LockGuard(){mutex_->unlock();std::cout << "解锁成功...." << std::endl;}private:Mutex *mutex_;
};

🐬7.7头文件util.hpp

#pragma once#include <iostream>
#include <string>
#include <cstring>
#include <cstdlib>
#include <cassert>
#include <ctype.h>
#include <unistd.h>
#include <strings.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include "log.hpp"#define SOCKET_ERR 1
#define BIND_ERR   2
#define LISTEN_ERR 3
#define USAGE_ERR  4
#define CONN_ERR   5#define BUFFER_SIZE 1024

🐳7.6Makefile 文件

.PHONY:all
all:clientTcp serverTcpclientTcp: ClientTCP.ccg++ -o $@ $^ -std=c++11
serverTcp:ServerTCP.ccg++ -o $@ $^ -std=c++11 -lpthread.PHONY:clean
clean:rm -f serverTcp clientTcp

00007

🐋7.8 日志文件 log.hpp

#pragma once#include <cstdio>
#include <ctime>
#include <cstdarg>
#include <cassert>
#include <cstring>
#include <cerrno>
#include <stdlib.h>#define DEBUG 0
#define NOTICE 1
#define WARINING 2
#define FATAL 3const char *log_level[]={"DEBUG", "NOTICE", "WARINING", "FATAL"};//四个提示等级// logMessage(DEBUG, "%d", 10);
void logMessage(int level, const char *format, ...)//可变参数
{assert(level >= DEBUG);assert(level <= FATAL);char *name = getenv("USER");char logInfo[1024];//存储日志数据va_list ap; // ap -> char*                    va_list是一种允许您操作变量参数的类型,va_start(ap, format);                        //va_start用于初始化 ava_list以指向第一个变量参数vsnprintf(logInfo, sizeof(logInfo)-1, format, ap);va_end(ap); // ap = NULLFILE *out = (level == FATAL) ? stderr:stdout;fprintf(out, "%s | %u | %s | %s\n", \log_level[level], \(unsigned int)time(nullptr),\name == nullptr ? "unknow":name,\logInfo);}

注:本程序是基于Linux系统下进行的,请在Linux环境下进行运行,本文为原创作品,各位转载请说明出处,创作不易,点赞支持技术大涨~~早日进大厂 ,关于程序有任何问题请在评论区留言…

🦈 🐊 🐅 🐆 🦓 🦍 🦧 🦣 🐘 🦛 🦏 🐪 🐫 🦒 🦘 🐃 🐂 🐄 🐎 🐖 🐏 🐑 🦙 🐐 🦌 🐕 🐩 🦮 🐕‍🦺 🐈 🐈‍⬛

相关文章:

【网络编程】C++实现网络通信服务器程序||计算机网络课设||Linux系统编程||TCP协议(附源码)

TCP网络服务器 &#x1f40d; 1.程序简洁&#x1f98e;2. 服务端ServerTcp程序介绍&#x1f996;3.线程池ThreadPool介绍&#x1f995; 4.任务类Task介绍&#x1f419;5. 客户端Client介绍&#x1f991;6.运行结果&#xff1a;&#x1f990; 7. 源码&#x1f99e;7.1 serverTcp…...

C语言类型占内存大小

C语言类型占内存大小 C语言数据类型sizeof测试基本数据类型所占字符大小运行结果数据模型 C语言数据类型 sizeof测试基本数据类型所占字符大小 #include <stdio.h>int main() {char a;short b;int c;long d;float e;double f;printf("char %d\n", sizeof (a…...

使用GPT-4生成训练数据微调GPT-3.5 RAG管道

OpenAI在2023年8月22日宣布&#xff0c;现在可以对GPT-3.5 Turbo进行微调了。也就是说&#xff0c;我们可以自定义自己的模型了。然后LlamaIndex就发布了0.8.7版本&#xff0c;集成了微调OpenAI gpt-3.5 turbo的功能 也就是说&#xff0c;我们现在可以使用GPT-4生成训练数据&a…...

RUST 每日一省:模式匹配

我们经常使用let 语句创建新的变量绑定——但是 let 的功能并不仅限于此。事实上&#xff0c; let 语句是一个模式匹配语句。它允许我们根据内部结构对值进行操作和判断&#xff0c;或者可以用于从代数数据类型中提取值。 let tuple (1_i32, false, 3f32); let (head, center…...

利用Jmeter做接口测试(功能测试)全流程分析

利用Jmeter做接口测试怎么做呢&#xff1f;过程真的是超级简单。 明白了原理以后&#xff0c;把零碎的知识点填充进去就可以了。所以在学习的过程中&#xff0c;不管学什么&#xff0c;我一直都强调的是要循序渐进&#xff0c;和明白原理和逻辑。这篇文章就来介绍一下如何利用…...

依赖导入失败场景和解决方案

在使用 Maven 构建项目时&#xff0c;可能会发生依赖项下载错误的情况&#xff0c;主要原因有以下几种&#xff1a; 下载依赖时出现网络故障或仓库服务器宕机等原因&#xff0c;导致无法连接至 Maven 仓库&#xff0c;从而无法下载依赖。 依赖项的版本号或配置文件中的版本号错…...

DiffBIR: Towards Blind Image Restoration with Generative Diffusion Prior

DiffBIR: 基于生成扩散先验的盲图像恢复 论文链接&#xff1a;https://arxiv.org/abs/2308.15070 项目链接&#xff1a;https://github.com/XPixelGroup/DiffBIR Abstract 我们提出了DiffBIR&#xff0c;它利用预训练的文本到图像扩散模型来解决盲图像恢复问题。我们的框架采…...

pycharm如何配置 .gitignore 文件

参考&#xff1a;https://zongweizhou1.github.io/2019/06/16/pycharm-gitignore/ .gitignore 文件本身不需要纳入版本控制&#xff0c;在 .gitignore 文件中写入“.gitignore"忽略即可...

【Spring面试题】AOP相关面试题:概念?使用场景?如何使用?核心?

什么是AOP AOP是面向切面&#xff0c;面向切面编程&#xff0c;是通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术。对多个对象共同行为封装成一个模块叫切面,然后某个方法为切点。 通俗的讲&#xff1a;就是在一些代码中做重复操作的时候&#xff0c;我们为了…...

Yolov5的tensorRT加速(python)

地址&#xff1a;https://github.com/wang-xinyu/tensorrtx/tree/master/yolov5 下载yolov5代码 方法一&#xff1a;使用torch2trt 安装torch2trt与tensorRT 参考博客&#xff1a;https://blog.csdn.net/dou3516/article/details/124538557 先从github拉取torch2trt源码 ht…...

设计模式(1) - UML类图

1、前言 最近在阅读 Android 源码&#xff0c;时常碰到代码中有一些巧妙的写法&#xff0c;简单的如 MediaPlayerService 中的 IFactory&#xff0c;我知道它是工厂模式&#xff0c;但是却不十分清楚它为什么这么用&#xff1b;复杂点的像 NuPlayer 中的 DeferredActions 机制…...

3D异常检测论文笔记 | Shape-Guided Dual-Memory Learning for 3D Anomaly Detection

文章目录 摘要一、介绍三、方法3.1. 形状引导专家学习3.2. Shape-Guided推理 摘要 我们提出了一个形状引导的专家学习框架来解决无监督的三维异常检测问题。我们的方法是建立在两个专门的专家模型的有效性和他们的协同从颜色和形状模态定位异常区域。第一个专家利用几何信息通…...

如何将枯燥的大数据进行可视化处理?

在数字时代&#xff0c;大数据已经成为商业、科学、政府和日常生活中不可或缺的一部分。然而&#xff0c;大数据本身往往是枯燥的、难以理解的数字和文字&#xff0c;如果没有有效的方式将其可视化&#xff0c;就会错失其中的宝贵信息。以下是一些方法&#xff0c;可以将枯燥的…...

linux bash中 test命令详解

test命令用于检查某个条件是否成立。它可以进行数值、字符和文件三方面的测试。 1、数值测试 -eq 等于-ne 不等于-gt 大于-ge 大于或等于-lt 小于-le 小于或等于 例如&#xff0c;我们可以测试两个变量是否相等&#xff1a; num1100 num2200 if test $num1 -eq $num2 thene…...

获取当前时间并转换为想要的格式

转换为YYYY-MM-DD格式 function getCurrentDate() {var today new Date();var year today.getFullYear();var month today.getMonth() 1; // 月份从0开始&#xff0c;需要加1var day today.getDate();return year - (month < 10 ? (0 month) : month) - (day &…...

如何实现自动化测试?

一、首先我们要清楚自动化测试的分类 以实现方式可分为UI自动化和接口自动化。UI自动化可用selenium等工具实现&#xff0c;接口自动化可用使用RobotFramework和Jmeter等工具实现&#xff0c;Jmeter也可做性能自动化&#xff0c;压力测试。 二、平时自动化测试怎么做 1. UI和…...

c++中的对齐问题

c中的对齐问题 需要对齐的原因 尽管内存是以字节为单位&#xff0c;但是大部分处理器并不是按字节块来存取内存的.它一般会以双字节,四字节,8字节,16字节甚至32字节为单位来存取内存&#xff0c;我们将上述这些存取单位称为内存存取粒度. 现在考虑4字节存取粒度的处理器取in…...

力扣(LeetCode)算法_C++—— 存在重复元素

给你一个整数数组 nums 。如果任一值在数组中出现 至少两次 &#xff0c;返回 true &#xff1b;如果数组中每个元素互不相同&#xff0c;返回 false 。 示例 1&#xff1a; 输入&#xff1a;nums [1,2,3,1] 输出&#xff1a;true 示例 2&#xff1a; 输入&#xff1a;nums …...

OpenCV实现Photoshop曲线调整

《QT 插件化图像算法研究平台》有仿Photoshop曲线调整图像的功能&#xff0c;包括RGB曲线调整和HSV曲线调整。 Photoshop曲线调整原理&#xff1a;RGB、HSV各通道曲线&#xff0c;可以理解为一个值映射&#xff08;值转换&#xff09;函数。X轴是输入&#xff0c;Y轴是输出。x0…...

【探索Linux】—— 强大的命令行工具 P.8(进程优先级、环境变量)

阅读导航 前言一、进程优先级1. 优先级概念2. Linux查看系统进程3. PRI&#xff08;Priority&#xff09;和NI&#xff08;Nice&#xff09; 二、环境变量1. 概念2. 查看环境变量方法3. 环境变量的组织方式4.通过代码获取环境变量5. 环境变量的特点 总结温馨提示 前言 前面我们…...

蓝牙协议栈BLE

前言 这阵子用到蓝牙比较多&#xff0c;想写一个专栏专门讲解蓝牙协议及其应用&#xff0c;本篇是第一篇文章&#xff0c;讲解低功耗蓝牙和蓝牙协议栈。 参考网上各大神文章&#xff0c;及瑞萨的文章&#xff0c;参考GPT&#xff0c;并且加入了一些本人的理解。 图片部分源自…...

企业架构LNMP学习笔记17

反向代理&#xff1a; 反向代理服务器和真实访问的服务器是在一起的&#xff0c;有关联的。 根据实际业务需求&#xff0c;分发代理页面到不同的解释器。常见于代理后端服务器。 安装apache服务器&#xff1a; yum install -y httpd 修改配置文件&#xff1a; vim /et/http…...

php 获取每月开始结束时间,指定月份的开始结束时间戳

php 获取指定月份的开始结束时间戳。 /** * * 获取指定年月的开始和结束时间戳 * param int $year 年份 * param int $month 月份 * return array(开始时间,结束时间) */ function getMonthBeginAndEnd($year 0, $month 0) {$year $year ? $year : date(Y);$month $month…...

Docker技术入门| Part03:Dockerfile详解(Dockerfile概念、Dockerfile 指令、使用Dockerfile构建镜像)

文章目录 1. Dockerfile概念2. Dockerfile 指令FROM 指定基础镜像RUN执行命令CMD 容器启动命令COPY 复制文件ADD 更高级的复制文件ENV 设置环境变量ARG 构建参数VOLUME 定义匿名卷EXPOSE 暴露端口WORKDIR 指定工作目录USER 指定当前用户LABEL 为镜像添加元数据SHELL 指令 3. 使…...

分享一个有意思的线程相关的程序运行题

翻开之前的代码&#xff0c;发现了一个有意思的代码&#xff0c;猜以下代码的运行结果&#xff1a; package thread;/*** author heyunlin* version 1.0*/ public class ThreadMethodExample {public static void main(String[] args) {Thread thread new Thread(new Runnabl…...

集合的进阶学习

集合体系结构 Collection 单列集合 包含List Set List 包含ArrayList LinkedList Set包含HashSet TreeSet HashSet包含LinkedHashSet List系列集合&#xff1a;添加的元素是有序的、可重复、有索引 Set系列集合&#xff1a;添加的元素是无序的、不重复、无索引 Collectio…...

Java真过饱和了吗?现在学Java迟了?

Java行业内幕揭秘 我是某有名机构的线下课Java老师&#xff0c;负责Java热门框架教学&#xff0c;如Spring、Spring MVC、Spring Boot。但最近被解雇了&#xff0c;让我来吐槽一下。Java现在的学习人数真的太多太多了。 Java的学习饱和度 Java学习的人太多&#xff0c;给你一…...

glibc2.35-通过tls_dtor_list劫持exit执行流程

前言 glibc2.35删除了malloc_hook、free_hook以及realloc_hook&#xff0c;通过劫持这三个hook函数执行system已经不可行了。 传统堆漏洞利用是利用任意地址写改上上述几个hook从而执行system&#xff0c;在移除之后则需要找到同样只需要修改某个地址值并且能够造成程序流劫持…...

linux-OpenSSL升级

1.安装编译所需的安装包 yum install -y gcc make perl zlib-devel 2.从 OpenSSL 官网下载&#xff08;https://www.openssl.org/source/openssl-1.1.1v.tar.gz&#xff09; 注:如果原先版本为1.x.x,升级时还是需要选择1.x.x 3. 编译安装 # 解压tar -xvf openssl-1.1.1v.tar…...

Nginx全家桶配置详解

源码包安装NGINX A&#xff0c;搭建Web Server&#xff0c;任意HTML页面&#xff0c;其8080端口提供Web访问服务&#xff0c;截图成功访问http(s)&#xff1a;//[Server1]:8080并且回显Web页面。保留Server1&#xff0c;但是不允许直接访问Server 1&#xff0c;再部署1套NGINX …...