当前位置: 首页 > 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. 环境变量的特点 总结温馨提示 前言 前面我们…...

调用支付宝接口响应40004 SYSTEM_ERROR问题排查

在对接支付宝API的时候&#xff0c;遇到了一些问题&#xff0c;记录一下排查过程。 Body:{"datadigital_fincloud_generalsaas_face_certify_initialize_response":{"msg":"Business Failed","code":"40004","sub_msg…...

1688商品列表API与其他数据源的对接思路

将1688商品列表API与其他数据源对接时&#xff0c;需结合业务场景设计数据流转链路&#xff0c;重点关注数据格式兼容性、接口调用频率控制及数据一致性维护。以下是具体对接思路及关键技术点&#xff1a; 一、核心对接场景与目标 商品数据同步 场景&#xff1a;将1688商品信息…...

Nuxt.js 中的路由配置详解

Nuxt.js 通过其内置的路由系统简化了应用的路由配置&#xff0c;使得开发者可以轻松地管理页面导航和 URL 结构。路由配置主要涉及页面组件的组织、动态路由的设置以及路由元信息的配置。 自动路由生成 Nuxt.js 会根据 pages 目录下的文件结构自动生成路由配置。每个文件都会对…...

Qt Http Server模块功能及架构

Qt Http Server 是 Qt 6.0 中引入的一个新模块&#xff0c;它提供了一个轻量级的 HTTP 服务器实现&#xff0c;主要用于构建基于 HTTP 的应用程序和服务。 功能介绍&#xff1a; 主要功能 HTTP服务器功能&#xff1a; 支持 HTTP/1.1 协议 简单的请求/响应处理模型 支持 GET…...

Java-41 深入浅出 Spring - 声明式事务的支持 事务配置 XML模式 XML+注解模式

点一下关注吧&#xff01;&#xff01;&#xff01;非常感谢&#xff01;&#xff01;持续更新&#xff01;&#xff01;&#xff01; &#x1f680; AI篇持续更新中&#xff01;&#xff08;长期更新&#xff09; 目前2025年06月05日更新到&#xff1a; AI炼丹日志-28 - Aud…...

Psychopy音频的使用

Psychopy音频的使用 本文主要解决以下问题&#xff1a; 指定音频引擎与设备&#xff1b;播放音频文件 本文所使用的环境&#xff1a; Python3.10 numpy2.2.6 psychopy2025.1.1 psychtoolbox3.0.19.14 一、音频配置 Psychopy文档链接为Sound - for audio playback — Psy…...

Caliper 配置文件解析:config.yaml

Caliper 是一个区块链性能基准测试工具,用于评估不同区块链平台的性能。下面我将详细解释你提供的 fisco-bcos.json 文件结构,并说明它与 config.yaml 文件的关系。 fisco-bcos.json 文件解析 这个文件是针对 FISCO-BCOS 区块链网络的 Caliper 配置文件,主要包含以下几个部…...

OpenLayers 分屏对比(地图联动)

注&#xff1a;当前使用的是 ol 5.3.0 版本&#xff0c;天地图使用的key请到天地图官网申请&#xff0c;并替换为自己的key 地图分屏对比在WebGIS开发中是很常见的功能&#xff0c;和卷帘图层不一样的是&#xff0c;分屏对比是在各个地图中添加相同或者不同的图层进行对比查看。…...

Maven 概述、安装、配置、仓库、私服详解

目录 1、Maven 概述 1.1 Maven 的定义 1.2 Maven 解决的问题 1.3 Maven 的核心特性与优势 2、Maven 安装 2.1 下载 Maven 2.2 安装配置 Maven 2.3 测试安装 2.4 修改 Maven 本地仓库的默认路径 3、Maven 配置 3.1 配置本地仓库 3.2 配置 JDK 3.3 IDEA 配置本地 Ma…...

10-Oracle 23 ai Vector Search 概述和参数

一、Oracle AI Vector Search 概述 企业和个人都在尝试各种AI&#xff0c;使用客户端或是内部自己搭建集成大模型的终端&#xff0c;加速与大型语言模型&#xff08;LLM&#xff09;的结合&#xff0c;同时使用检索增强生成&#xff08;Retrieval Augmented Generation &#…...