承德网站开发国内wordpress免费主题

张小明 2026/1/9 7:44:12
承德网站开发,国内wordpress免费主题,wordpress支付宝付款,东莞网页开发基于C的UDP网络通信系统设计与实现 前言 在网络编程领域#xff0c;UDP#xff08;User Datagram Protocol#xff0c;用户数据报协议#xff09;作为一种无连接的传输层协议#xff0c;以其高效、低延迟的特性在实时性要求高的应用场景中占据重要地位。与TCP协议相比的UDP网络通信系统设计与实现前言在网络编程领域UDPUser Datagram Protocol用户数据报协议作为一种无连接的传输层协议以其高效、低延迟的特性在实时性要求高的应用场景中占据重要地位。与TCP协议相比UDP不需要建立连接不保证数据包的顺序和可靠性但正是这种轻量级特性使其在视频流、在线游戏、DNS查询等领域得到广泛应用。本文将深入探讨如何从零开始构建一个完整的UDP通信系统涵盖服务器端、客户端的设计与实现包括套接字编程的核心概念、关键系统调用、错误处理机制以及实际应用中的注意事项。通过本文的学习读者不仅能够掌握UDP网络编程的基本技能还能深入理解网络通信的底层原理。本文实现的UDP通信系统具有以下特点完整的服务器/客户端架构详细的错误处理和日志记录可配置的服务器参数跨平台兼容性考虑丰富的代码示例和详细注释一、UDP服务器UdpServer.hpp1.1 基本框架设计UDP服务器的设计需要遵循模块化、可扩展的原则。我们将服务器封装为一个类包含初始化、运行和清理等基本功能。#ifndefUDPSERVER_HPP#defineUDPSERVER_HPP#includeiostream#includestring#includecstring#includecstdlib#includeunistd.h#includearpa/inet.h#includesys/socket.h#includesys/types.h#includenetinet/in.h#includethread#includevector#includememory#includeatomic#includefunctional#includeLog.hppclassUdpServer{private:intport_;// 服务器端口intsockfd_;// 套接字描述符std::atomicboolis_running_;// 服务器运行状态structsockaddr_inserver_addr_;// 服务器地址结构structsockaddr_inclient_addr_;// 客户端地址结构socklen_t client_addr_len_;// 客户端地址长度// 服务器配置参数size_t buffer_size_;// 缓冲区大小inttimeout_sec_;// 接收超时时间(秒)inttimeout_usec_;// 接收超时时间(微秒)boolreuse_addr_;// 是否重用地址public:// 构造函数explicitUdpServer(intport8080);// 析构函数~UdpServer();// 禁止拷贝构造和赋值UdpServer(constUdpServer)delete;UdpServeroperator(constUdpServer)delete;// 初始化服务器boolInit();// 运行服务器voidRun();// 停止服务器voidStop();// 设置配置参数voidSetBufferSize(size_t size){buffer_size_size;}voidSetTimeout(intsec,intusec0){timeout_sec_sec;timeout_usec_usec;}voidSetReuseAddr(boolreuse){reuse_addr_reuse;}private:// 创建套接字boolCreateSocket();// 绑定地址boolBindAddress();// 设置套接字选项boolSetSocketOptions();// 处理接收到的数据virtualvoidProcessData(constchar*data,ssize_t len,conststructsockaddr_inclient_addr);// 发送响应boolSendResponse(constchar*data,ssize_t len,conststructsockaddr_inclient_addr);// 清理资源voidCleanup();};#endif// UDPSERVER_HPP1.2 初始化函数Init详解初始化函数是服务器启动的第一步它负责套接字创建、地址绑定和选项设置等关键操作。boolUdpServer::Init(){// 1. 创建日志实例Logger::Instance().Init(udp_server.log,LogLevel::INFO);LOG_INFO(Starting UDP server initialization...);// 2. 创建套接字if(!CreateSocket()){LOG_ERROR(Failed to create socket);returnfalse;}// 3. 设置套接字选项if(!SetSocketOptions()){LOG_ERROR(Failed to set socket options);close(sockfd_);returnfalse;}// 4. 绑定地址if(!BindAddress()){LOG_ERROR(Failed to bind address);close(sockfd_);returnfalse;}// 5. 初始化客户端地址结构memset(client_addr_,0,sizeof(client_addr_));client_addr_len_sizeof(client_addr_);LOG_INFO(UDP server initialized successfully on port %d,port_);LOG_INFO(Buffer size: %zu bytes,buffer_size_);LOG_INFO(Timeout: %d seconds %d microseconds,timeout_sec_,timeout_usec_);returntrue;}boolUdpServer::CreateSocket(){// 使用AF_INET表示IPv4SOCK_DGRAM表示UDP协议sockfd_socket(AF_INET,SOCK_DGRAM,0);if(sockfd_0){LOG_ERROR(Socket creation failed: %s,strerror(errno));returnfalse;}LOG_DEBUG(Socket created successfully, fd: %d,sockfd_);returntrue;}boolUdpServer::SetSocketOptions(){intoptval1;// 设置地址重用选项避免Address already in use错误if(reuse_addr_){if(setsockopt(sockfd_,SOL_SOCKET,SO_REUSEADDR,optval,sizeof(optval))0){LOG_WARN(Failed to set SO_REUSEADDR: %s,strerror(errno));// 注意这不是致命错误可以继续运行}else{LOG_DEBUG(SO_REUSEADDR set successfully);}}// 设置接收超时if(timeout_sec_0||timeout_usec_0){structtimevaltv;tv.tv_sectimeout_sec_;tv.tv_usectimeout_usec_;if(setsockopt(sockfd_,SOL_SOCKET,SO_RCVTIMEO,tv,sizeof(tv))0){LOG_WARN(Failed to set receive timeout: %s,strerror(errno));}else{LOG_DEBUG(Receive timeout set to %ld.%06ld seconds,tv.tv_sec,tv.tv_usec);}}// 设置发送缓冲区大小intsend_buf_size1024*1024;// 1MBif(setsockopt(sockfd_,SOL_SOCKET,SO_SNDBUF,send_buf_size,sizeof(send_buf_size))0){LOG_WARN(Failed to set send buffer size: %s,strerror(errno));}// 设置接收缓冲区大小intrecv_buf_size1024*1024;// 1MBif(setsockopt(sockfd_,SOL_SOCKET,SO_RCVBUF,recv_buf_size,sizeof(recv_buf_size))0){LOG_WARN(Failed to set receive buffer size: %s,strerror(errno));}returntrue;}boolUdpServer::BindAddress(){// 初始化服务器地址结构memset(server_addr_,0,sizeof(server_addr_));// 设置地址族为IPv4server_addr_.sin_familyAF_INET;// 设置端口使用htons进行字节序转换server_addr_.sin_porthtons(port_);// 设置IP地址为INADDR_ANY表示监听所有网络接口server_addr_.sin_addr.s_addrhtonl(INADDR_ANY);// 绑定套接字到指定地址和端口if(bind(sockfd_,(structsockaddr*)server_addr_,sizeof(server_addr_))0){LOG_ERROR(Bind failed on port %d: %s,port_,strerror(errno));returnfalse;}// 获取实际绑定的地址信息structsockaddr_inactual_addr;socklen_t actual_lensizeof(actual_addr);if(getsockname(sockfd_,(structsockaddr*)actual_addr,actual_len)0){charip_str[INET_ADDRSTRLEN];inet_ntop(AF_INET,actual_addr.sin_addr,ip_str,sizeof(ip_str));LOG_INFO(Server bound to %s:%d,ip_str,ntohs(actual_addr.sin_port));}returntrue;}1.3 关键系统调用详解1.3.1 inet_addr函数inet_addr函数用于将点分十进制表示的IPv4地址转换为网络字节序的32位整数。虽然本文代码中使用的是inet_pton更安全的版本但理解inet_addr仍然很重要。// inet_addr的使用示例constchar*ip_str192.168.1.100;in_addr_t addrinet_addr(ip_str);if(addrINADDR_NONE){LOG_ERROR(Invalid IP address: %s,ip_str);}else{LOG_DEBUG(IP %s converted to network byte order: 0x%08x,ip_str,addr);// 转换回点分十进制格式structin_addraddr_struct;addr_struct.s_addraddr;char*ip_str_backinet_ntoa(addr_struct);LOG_DEBUG(Converted back to string: %s,ip_str_back);}// 现代推荐使用inet_pton更安全支持IPv6structsockaddr_inaddr;if(inet_pton(AF_INET,ip_str,addr.sin_addr)0){LOG_ERROR(Invalid IP address format: %s,ip_str);}1.3.2 bzero和memset函数bzero是BSD系统中用于将内存区域清零的函数而memset是标准C库函数功能更通用。// bzero的使用传统方式structsockaddr_inaddr;bzero(addr,sizeof(addr));// 将整个结构体清零// memset的等效用法memset(addr,0,sizeof(addr));// 更标准的做法// memset的更多用途charbuffer[1024];// 全部设置为0memset(buffer,0,sizeof(buffer));// 全部设置为特定值memset(buffer,A,sizeof(buffer));// 部分设置memset(buffer,0,100);// 只清空前100字节// 性能比较对于大内存块memset通常经过优化性能更好1.4 服务器运行函数RunRun函数是服务器的核心负责循环接收客户端请求并处理。voidUdpServer::Run(){if(sockfd_0){LOG_ERROR(Cannot run server: socket not initialized);return;}is_running_true;LOG_INFO(UDP server started, waiting for connections...);// 分配接收缓冲区std::vectorcharbuffer(buffer_size_);// 主循环while(is_running_){// 重置客户端地址信息memset(client_addr_,0,sizeof(client_addr_));client_addr_len_sizeof(client_addr_);// 接收数据ssize_t recv_lenrecvfrom(sockfd_,buffer.data(),buffer.size()-1,0,(structsockaddr*)client_addr_,client_addr_len_);if(recv_len0){// 处理接收错误if(errnoEAGAIN||errnoEWOULDBLOCK){// 超时继续循环continue;}elseif(errnoEINTR){// 被信号中断LOG_DEBUG(recvfrom interrupted by signal);continue;}else{LOG_ERROR(recvfrom failed: %s,strerror(errno));break;}}elseif(recv_len0){// UDP中recvfrom返回0表示收到了0字节的数据包LOG_DEBUG(Received empty datagram);continue;}// 确保字符串以null结尾buffer[recv_len]\0;// 获取客户端信息charclient_ip[INET_ADDRSTRLEN];inet_ntop(AF_INET,client_addr_.sin_addr,client_ip,sizeof(client_ip));uint16_tclient_portntohs(client_addr_.sin_port);LOG_DEBUG(Received %zd bytes from %s:%d,recv_len,client_ip,client_port);LOG_DEBUG(Data: %s,buffer.data());// 处理数据ProcessData(buffer.data(),recv_len,client_addr_);}LOG_INFO(UDP server stopped);Cleanup();}voidUdpServer::ProcessData(constchar*data,ssize_t len,conststructsockaddr_inclient_addr){// 默认实现原样返回数据echo服务器LOG_DEBUG(Processing %zd bytes of data,len);// 构造响应std::string responseServer received: ;response.append(data,len);// 发送响应if(!SendResponse(response.c_str(),response.length(),client_addr)){LOG_ERROR(Failed to send response to client);}}boolUdpServer::SendResponse(constchar*data,ssize_t len,conststructsockaddr_inclient_addr){if(len0){LOG_WARN(Attempting to send empty data);returntrue;// 空数据发送成功}// 发送数据ssize_t sent_lensendto(sockfd_,data,len,0,(conststructsockaddr*)client_addr,sizeof(client_addr));if(sent_len0){LOG_ERROR(sendto failed: %s,strerror(errno));returnfalse;}if(sent_len!len){LOG_WARN(Partial send: %zd of %zd bytes sent,sent_len,len);}// 获取客户端信息用于日志charclient_ip[INET_ADDRSTRLEN];inet_ntop(AF_INET,client_addr.sin_addr,client_ip,sizeof(client_ip));uint16_tclient_portntohs(client_addr.sin_port);LOG_DEBUG(Sent %zd bytes to %s:%d,sent_len,client_ip,client_port);returntrue;}1.5 recvfrom和sendto函数深度解析1.5.1 recvfrom函数recvfrom是UDP接收数据的核心函数它不仅可以接收数据还能获取发送者的地址信息。/** * recvfrom函数原型 * ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags, * struct sockaddr *src_addr, socklen_t *addrlen); * * 参数说明 * - sockfd: 套接字描述符 * - buf: 接收缓冲区 * - len: 缓冲区大小 * - flags: 标志位常用值 * * 0: 默认行为 * * MSG_WAITALL: 等待所有数据对UDP通常无效 * * MSG_DONTWAIT: 非阻塞模式 * * MSG_PEEK: 查看数据但不从缓冲区移除 * - src_addr: 发送方地址输出参数 * - addrlen: 地址长度输入输出参数 * * 返回值 * - 成功接收到的字节数 * - 失败-1设置errno * - 连接关闭TCP或空数据包UDP0 */// recvfrom的完整示例voidReceiveExample(intsockfd){structsockaddr_inclient_addr;socklen_t addr_lensizeof(client_addr);charbuffer[4096];// 设置接收超时structtimevaltv;tv.tv_sec5;tv.tv_usec0;setsockopt(sockfd,SOL_SOCKET,SO_RCVTIMEO,tv,sizeof(tv));// 接收数据ssize_t recv_lenrecvfrom(sockfd,buffer,sizeof(buffer)-1,MSG_DONTWAIT,// 非阻塞模式(structsockaddr*)client_addr,addr_len);if(recv_len0){buffer[recv_len]\0;// 获取客户端信息charip_str[INET_ADDRSTRLEN];inet_ntop(AF_INET,client_addr.sin_addr,ip_str,sizeof(ip_str));uint16_tportntohs(client_addr.sin_port);LOG_INFO(Received from %s:%d: %s,ip_str,port,buffer);// 处理不同的消息类型ProcessMessage(buffer,recv_len,client_addr);}elseif(recv_len0){LOG_DEBUG(Received empty datagram);}else{// 错误处理if(errnoEAGAIN||errnoEWOULDBLOCK){LOG_DEBUG(No data available (non-blocking));}elseif(errnoEINTR){LOG_DEBUG(Interrupted by signal);}else{LOG_ERROR(Receive error: %s,strerror(errno));}}}// 处理不同类型的消息voidProcessMessage(constchar*data,ssize_t len,conststructsockaddr_inclient_addr){// 简单的协议处理示例if(len4strncmp(data,PING,4)0){LOG_DEBUG(Received PING request);SendResponse(PONG,4,client_addr);}elseif(len4strncmp(data,TIME,4)0){time_t nowtime(nullptr);std::string time_strctime(now);SendResponse(time_str.c_str(),time_str.length(),client_addr);}elseif(len7strncmp(data,ECHO ,5)0){// 回显消息内容SendResponse(data5,len-5,client_addr);}else{std::string responseUnknown command: ;response.append(data,len);SendResponse(response.c_str(),response.length(),client_addr);}}1.5.2 sendto函数sendto是UDP发送数据的核心函数用于向指定地址发送数据报。/** * sendto函数原型 * ssize_t sendto(int sockfd, const void *buf, size_t len, int flags, * const struct sockaddr *dest_addr, socklen_t addrlen); * * 参数说明 * - sockfd: 套接字描述符 * - buf: 发送缓冲区 * - len: 要发送的数据长度 * - flags: 标志位常用值 * * 0: 默认行为 * * MSG_DONTWAIT: 非阻塞模式 * * MSG_CONFIRM: 确认路由有效Linux特有 * * MSG_MORE: 还有更多数据要发送 * - dest_addr: 目标地址 * - addrlen: 地址长度 * * 返回值 * - 成功发送的字节数可能小于len * - 失败-1设置errno */// sendto的完整示例boolSendData(intsockfd,constvoid*data,size_t len,conststructsockaddr_indest_addr){if(len0){LOG_WARN(Attempting to send zero-length data);returntrue;}// 检查数据包大小UDP最大约64KB实际建议小于1500字节避免分片if(len65507){// 65535 - 20(IP头) - 8(UDP头)LOG_ERROR(Datagram too large: %zu bytes (max: 65507),len);returnfalse;}if(len1400){LOG_WARN(Large datagram: %zu bytes (may be fragmented),len);}// 分块发送大数据如果需要constsize_t MAX_CHUNK1400;// 避免IP分片的推荐大小size_t total_sent0;while(total_sentlen){size_t chunk_sizestd::min(MAX_CHUNK,len-total_sent);constchar*chunk_startstatic_castconstchar*(data)total_sent;ssize_t sentsendto(sockfd,chunk_start,chunk_size,0,(conststructsockaddr*)dest_addr,sizeof(dest_addr));if(sent0){LOG_ERROR(Failed to send chunk: %s (sent %zu/%zu bytes),strerror(errno),total_sent,len);returnfalse;}total_sentsent;// 添加小延迟避免拥塞if(chunk_sizeMAX_CHUNKtotal_sentlen){usleep(1000);// 1ms延迟}}LOG_DEBUG(Successfully sent %zu bytes to %s:%d,total_sent,inet_ntoa(dest_addr.sin_addr),ntohs(dest_addr.sin_port));returntrue;}// 发送不同类型的消息voidSendVariousMessages(intsockfd,conststructsockaddr_indest_addr){// 1. 发送字符串constchar*textHello, UDP Server!;SendData(sockfd,text,strlen(text),dest_addr);// 2. 发送二进制数据structBinaryData{uint32_tmagic;uint16_tversion;uint8_ttype;uint8_tdata[256];}binary_msg;binary_msg.magichtonl(0xDEADBEEF);binary_msg.versionhtons(1);binary_msg.type0x42;memset(binary_msg.data,0xAA,sizeof(binary_msg.data));SendData(sockfd,binary_msg,sizeof(binary_msg),dest_addr);// 3. 发送结构化数据JSON格式std::string json_msgR({ command: update, timestamp: )std::to_string(time(nullptr))R(, data: {temperature: 23.5, humidity: 65.2} });SendData(sockfd,json_msg.c_str(),json_msg.length(),dest_addr);// 4. 发送带序列号的消息for(inti0;i10;i){std::string seq_msgMessage #std::to_string(i);SendData(sockfd,seq_msg.c_str(),seq_msg.length(),dest_addr);// 添加延迟usleep(100000);// 100ms}}1.6 高级功能多线程处理和连接管理对于高性能UDP服务器我们需要考虑多线程处理和客户端连接管理。// 扩展UdpServer类添加多线程支持classAdvancedUdpServer:publicUdpServer{private:std::vectorstd::threadworker_threads_;std::atomicintthread_count_;intmax_workers_;// 线程池和工作队列std::queuestd::pairstd::vectorchar,sockaddr_intask_queue_;std::mutex queue_mutex_;std::condition_variable queue_cv_;public:AdvancedUdpServer(intport8080,intmax_workers4):UdpServer(port),max_workers_(max_workers),thread_count_(0){}~AdvancedUdpServer(){Stop();}boolInit()override{if(!UdpServer::Init()){returnfalse;}// 创建工作线程for(inti0;imax_workers_;i){worker_threads_.emplace_back(AdvancedUdpServer::WorkerThread,this,i);}LOG_INFO(Started %d worker threads,max_workers_);returntrue;}voidRun()override{if(sockfd_0){LOG_ERROR(Socket not initialized);return;}is_running_true;LOG_INFO(Advanced UDP server started on port %d,port_);std::vectorcharbuffer(buffer_size_);while(is_running_){structsockaddr_inclient_addr;socklen_t addr_lensizeof(client_addr);// 接收数据ssize_t recv_lenrecvfrom(sockfd_,buffer.data(),buffer.size()-1,0,(structsockaddr*)client_addr,addr_len);if(recv_len0){if(errnoEAGAIN||errnoEWOULDBLOCK){continue;}elseif(errnoEINTR){continue;}else{LOG_ERROR(Receive error: %s,strerror(errno));break;}}if(recv_len0){buffer[recv_len]\0;// 将任务加入队列{std::lock_guardstd::mutexlock(queue_mutex_);task_queue_.emplace(std::vectorchar(buffer.begin(),buffer.begin()recv_len),client_addr);}// 通知工作线程queue_cv_.notify_one();// 获取统计信息if(task_queue_.size()10){LOG_WARN(Task queue size: %zu,task_queue_.size());}}}// 通知所有工作线程退出queue_cv_.notify_all();// 等待所有线程结束for(autothread:worker_threads_){if(thread.joinable()){thread.join();}}LOG_INFO(Advanced UDP server stopped);Cleanup();}private:voidWorkerThread(intthread_id){thread_count_;LOG_DEBUG(Worker thread %d started,thread_id);while(is_running_){std::pairstd::vectorchar,sockaddr_intask;{std::unique_lockstd::mutexlock(queue_mutex_);queue_cv_.wait(lock,[this](){return!task_queue_.empty()||!is_running_;});if(!is_running_task_queue_.empty()){break;}if(!task_queue_.empty()){taskstd::move(task_queue_.front());task_queue_.pop();}else{continue;}}// 处理任务ProcessTask(task.first,task.second,thread_id);}thread_count_--;LOG_DEBUG(Worker thread %d stopped,thread_id);}voidProcessTask(conststd::vectorchardata,constsockaddr_inclient_addr,intthread_id){// 获取客户端信息charclient_ip[INET_ADDRSTRLEN];inet_ntop(AF_INET,client_addr.sin_addr,client_ip,sizeof(client_ip));uint16_tclient_portntohs(client_addr.sin_port);LOG_DEBUG(Thread %d processing %zu bytes from %s:%d,thread_id,data.size(),client_ip,client_port);// 模拟处理时间std::this_thread::sleep_for(std::chrono::milliseconds(10));// 处理数据std::string responseThread std::to_string(thread_id) processed: std::string(data.begin(),data.end());SendResponse(response.c_str(),response.length(),client_addr);}};// 连接管理类classConnectionManager{private:structClientInfo{sockaddr_in address;time_t last_activity;uint64_tpacket_count;uint64_ttotal_bytes;ClientInfo(constsockaddr_inaddr):address(addr),last_activity(time(nullptr)),packet_count(0),total_bytes(0){}};std::unordered_mapstd::string,ClientInfoclients_;std::mutex clients_mutex_;time_t cleanup_interval_;public:ConnectionManager(time_t cleanup_interval300)// 5分钟:cleanup_interval_(cleanup_interval){}// 更新客户端活动voidUpdateClient(constsockaddr_inaddr,size_t bytes){std::string keyGetClientKey(addr);std::lock_guardstd::mutexlock(clients_mutex_);autoitclients_.find(key);if(itclients_.end()){// 新客户端clients_.emplace(key,ClientInfo(addr));itclients_.find(key);charip_str[INET_ADDRSTRLEN];inet_ntop(AF_INET,addr.sin_addr,ip_str,sizeof(ip_str));LOG_INFO(New client connected: %s:%d,ip_str,ntohs(addr.sin_port));}// 更新统计信息it-second.last_activitytime(nullptr);it-second.packet_count;it-second.total_bytesbytes;}// 清理不活跃的连接voidCleanupInactiveClients(){time_t nowtime(nullptr);std::vectorstd::stringto_remove;{std::lock_guardstd::mutexlock(clients_mutex_);for(constautopair:clients_){if(now-pair.second.last_activitycleanup_interval_){to_remove.push_back(pair.first);}}for(constautokey:to_remove){constautoclientclients_[key];charip_str[INET_ADDRSTRLEN];inet_ntop(AF_INET,client.address.sin_addr,ip_str,sizeof(ip_str));LOG_INFO(Client %s:%d disconnected (inactive). Packets: %lu, Bytes: %lu,ip_str,ntohs(client.address.sin_port),client.packet_count,client.total_bytes);clients_.erase(key);}}if(!to_remove.empty()){LOG_INFO(Cleaned up %zu inactive clients,to_remove.size());}}// 获取客户端统计信息std::stringGetStats()const{std::lock_guardstd::mutexlock(clients_mutex_);std::stringstream ss;ssActive clients: clients_.size()\n;for(constautopair:clients_){charip_str[INET_ADDRSTRLEN];inet_ntop(AF_INET,pair.second.address.sin_addr,ip_str,sizeof(ip_str));ssip_str:ntohs(pair.second.address.sin_port) - Packets: pair.second.packet_count, Bytes: pair.second.total_bytes, Last activity: (time(nullptr)-pair.second.last_activity) seconds ago\n;}returnss.str();}private:std::stringGetClientKey(constsockaddr_inaddr)const{std::stringstream ss;ssinet_ntoa(addr.sin_addr):ntohs(addr.sin_port);returnss.str();}};二、Main.cc实现主程序负责初始化服务器并处理命令行参数。#includeiostream#includecsignal#includecstdlib#includememory#includeUdpServer.hpp#includeAdvancedUdpServer.hpp// 全局服务器指针用于信号处理std::unique_ptrUdpServerg_server;// 信号处理函数voidSignalHandler(intsignal){std::cout\nReceived signal signal, shutting down...std::endl;if(g_server){g_server-Stop();}}// 显示使用帮助voidShowUsage(constchar*program_name){std::coutUDP Server v1.0\n\n;std::coutUsage: program_name [options]\n\n;std::coutOptions:\n;std::cout -p, --port PORT Server port (default: 8080)\n;std::cout -b, --buffer SIZE Buffer size in bytes (default: 4096)\n;std::cout -t, --timeout SEC Receive timeout in seconds (default: 5)\n;std::cout -w, --workers NUM Number of worker threads (default: 1)\n;std::cout -a, --advanced Use advanced server with thread pool\n;std::cout -h, --help Show this help message\n;std::cout\nExamples:\n;std::cout program_name -p 9000 -b 8192\n;std::cout program_name --port 8080 --workers 4 --advanced\n;}// 解析命令行参数structServerConfig{intport8080;size_t buffer_size4096;inttimeout_sec5;inttimeout_usec0;intworkers1;booladvancedfalse;boolreuse_addrtrue;};ServerConfigParseArguments(intargc,char*argv[]){ServerConfig config;for(inti1;iargc;i){std::string argargv[i];if(arg-p||arg--port){if(i1argc){config.portstd::atoi(argv[i]);if(config.port0||config.port65535){std::cerrError: Port must be between 1 and 65535std::endl;exit(1);}}}elseif(arg-b||arg--buffer){if(i1argc){config.buffer_sizestd::atoi(argv[i]);if(config.buffer_size1024||config.buffer_size65536){std::cerrError: Buffer size must be between 1024 and 65536std::endl;exit(1);}}}elseif(arg-t||arg--timeout){if(i1argc){config.timeout_secstd::atoi(argv[i]);if(config.timeout_sec0){std::cerrError: Timeout must be non-negativestd::endl;exit(1);}}}elseif(arg-w||arg--workers){if(i1argc){config.workersstd::atoi(argv[i]);if(config.workers1||config.workers32){std::cerrError: Number of workers must be between 1 and 32std::endl;exit(1);}}}elseif(arg-a||arg--advanced){config.advancedtrue;}elseif(arg-h||arg--help){ShowUsage(argv[0]);exit(0);}elseif(arg--no-reuse){config.reuse_addrfalse;}else{std::cerrError: Unknown option argstd::endl;ShowUsage(argv[0]);exit(1);}}returnconfig;}intmain(intargc,char*argv[]){// 解析命令行参数ServerConfig configParseArguments(argc,argv);// 注册信号处理signal(SIGINT,SignalHandler);signal(SIGTERM,SignalHandler);try{std::cout UDP Server Starting \n;std::coutPort: config.port\n;std::coutBuffer size: config.buffer_size bytes\n;std::coutTimeout: config.timeout_sec seconds\n;std::coutWorkers: config.workers\n;std::coutMode: (config.advanced?Advanced:Basic)\n;std::cout\n\n;// 创建服务器实例if(config.advanced){g_serverstd::make_uniqueAdvancedUdpServer(config.port,config.workers);}else{g_serverstd::make_uniqueUdpServer(config.port);}// 配置服务器g_server-SetBufferSize(config.buffer_size);g_server-SetTimeout(config.timeout_sec,config.timeout_usec);g_server-SetReuseAddr(config.reuse_addr);// 初始化服务器if(!g_server-Init()){std::cerrFailed to initialize serverstd::endl;return1;}std::coutServer initialized successfully\n;std::coutPress CtrlC to stop the server\n\n;// 运行服务器g_server-Run();}catch(conststd::exceptione){std::cerrException: e.what()std::endl;return1;}catch(...){std::cerrUnknown exception occurredstd::endl;return1;}std::cout\nServer stopped gracefullystd::endl;return0;}// 性能测试函数voidRunPerformanceTest(intport){std::cout\n Performance Test \n;// 创建测试服务器autotest_serverstd::make_uniqueAdvancedUdpServer(port,4);test_server-SetBufferSize(65536);test_server-SetTimeout(1,0);if(!test_server-Init()){std::cerrFailed to initialize test serverstd::endl;return;}// 在后台运行服务器std::threadserver_thread([test_server](){test_server-Run();});// 给服务器时间启动std::this_thread::sleep_for(std::chrono::seconds(1));// 创建测试客户端intclient_socksocket(AF_INET,SOCK_DGRAM,0);if(client_sock0){std::cerrFailed to create test client socketstd::endl;return;}structsockaddr_inserver_addr;memset(server_addr,0,sizeof(server_addr));server_addr.sin_familyAF_INET;server_addr.sin_porthtons(port);server_addr.sin_addr.s_addrhtonl(INADDR_LOOPBACK);// 测试参数constintNUM_PACKETS10000;constintPACKET_SIZE1024;std::vectorchartest_data(PACKET_SIZE,X);autostart_timestd::chrono::high_resolution_clock::now();// 发送测试数据包for(inti0;iNUM_PACKETS;i){// 在数据中包含序列号memcpy(test_data.data(),i,sizeof(i));ssize_t sentsendto(client_sock,test_data.data(),PACKET_SIZE,0,(structsockaddr*)server_addr,sizeof(server_addr));if(sent!PACKET_SIZE){std::cerrFailed to send packet istd::endl;break;}// 每1000个包打印进度if((i1)%10000){std::coutSent (i1) packets...std::endl;}// 小延迟避免拥塞usleep(10);}autoend_timestd::chrono::high_resolution_clock::now();autodurationstd::chrono::duration_caststd::chrono::milliseconds(end_time-start_time);close(client_sock);// 停止服务器test_server-Stop();if(server_thread.joinable()){server_thread.join();}// 输出结果std::cout\nPerformance Test Results:\n;std::coutPackets sent: NUM_PACKETS\n;std::coutPacket size: PACKET_SIZE bytes\n;std::coutTotal data: (NUM_PACKETS*PACKET_SIZE/1024.0/1024.0) MB\n;std::coutTotal time: duration.count() ms\n;std::coutThroughput: (NUM_PACKETS*PACKET_SIZE*8.0/duration.count()/1000.0) Mbps\n;std::coutPackets per second: (NUM_PACKETS*1000.0/duration.count())\n;}三、UDP客户端UdpClient.cc3.1 基本框架设计UDP客户端的设计需要简洁高效支持多种操作模式。#ifndefUDPCLIENT_H#defineUDPCLIENT_H#includeiostream#includestring#includecstring#includecstdlib#includeunistd.h#includearpa/inet.h#includesys/socket.h#includesys/types.h#includenetinet/in.h#includevector#includechrono#includethread#includeatomic#includememory#includeiomanipclassUdpClient{private:intsockfd_;// 套接字描述符structsockaddr_inserver_addr_;// 服务器地址std::string server_ip_;// 服务器IP地址intserver_port_;// 服务器端口// 客户端状态std::atomicboolis_connected_;std::atomicboolis_running_;// 统计信息uint64_tpackets_sent_;uint64_tpackets_received_;uint64_tbytes_sent_;uint64_tbytes_received_;public:// 构造函数UdpClient(conststd::stringip127.0.0.1,intport8080);// 析构函数~UdpClient();// 初始化客户端boolInit();// 连接服务器boolConnect();// 发送数据boolSend(conststd::stringdata);boolSend(constvoid*data,size_t len);// 接收数据阻塞boolReceive(std::stringdata,inttimeout_ms5000);// 发送并等待响应boolSendAndReceive(conststd::stringsend_data,std::stringrecv_data,inttimeout_ms5000);// 运行交互模式voidRunInteractive();// 运行性能测试模式voidRunPerformanceTest(intnum_packets1000,intpacket_size1024);// 获取统计信息voidGetStats(uint64_tsent_packets,uint64_treceived_packets,uint64_tsent_bytes,uint64_treceived_bytes)const;// 重置统计信息voidResetStats();// 断开连接voidDisconnect();private:// 创建套接字boolCreateSocket();// 设置套接字选项boolSetSocketOptions();// 打印状态voidPrintStatus()const;// 显示帮助信息voidShowHelp()const;};#endif// UDPCLIENT_H3.2 创建套接字和连接#includeUdpClient.hUdpClient::UdpClient(conststd::stringip,intport):server_ip_(ip),server_port_(port),sockfd_(-1),is_connected_(false),is_running_(false),packets_sent_(0),packets_received_(0),bytes_sent_(0),bytes_received_(0){// 初始化服务器地址结构memset(server_addr_,0,sizeof(server_addr_));server_addr_.sin_familyAF_INET;server_addr_.sin_porthtons(server_port_);// 转换IP地址if(inet_pton(AF_INET,server_ip_.c_str(),server_addr_.sin_addr)0){std::cerrInvalid IP address: server_ip_std::endl;}}UdpClient::~UdpClient(){Disconnect();}boolUdpClient::Init(){// 创建套接字if(!CreateSocket()){std::cerrFailed to create socketstd::endl;returnfalse;}// 设置套接字选项if(!SetSocketOptions()){std::cerrFailed to set socket optionsstd::endl;close(sockfd_);returnfalse;}std::coutUDP client initializedstd::endl;std::coutServer: server_ip_:server_port_std::endl;returntrue;}boolUdpClient::CreateSocket(){// 创建UDP套接字sockfd_socket(AF_INET,SOCK_DGRAM,0);if(sockfd_0){std::cerrSocket creation failed: strerror(errno)std::endl;returnfalse;}std::coutSocket created successfully (fd: sockfd_)std::endl;returntrue;}boolUdpClient::SetSocketOptions(){intoptval1;// 设置接收超时structtimevaltv;tv.tv_sec5;tv.tv_usec0;if(setsockopt(sockfd_,SOL_SOCKET,SO_RCVTIMEO,tv,sizeof(tv))0){std::cerrFailed to set receive timeout: strerror(errno)std::endl;returnfalse;}// 启用广播如果需要optval1;if(setsockopt(sockfd_,SOL_SOCKET,SO_BROADCAST,optval,sizeof(optval))0){std::cerrWarning: Failed to enable broadcast: strerror(errno)std::endl;}// 设置缓冲区大小intbuf_size1024*1024;// 1MBif(setsockopt(sockfd_,SOL_SOCKET,SO_RCVBUF,buf_size,sizeof(buf_size))0){std::cerrWarning: Failed to set receive buffer: strerror(errno)std::endl;}if(setsockopt(sockfd_,SOL_SOCKET,SO_SNDBUF,buf_size,sizeof(buf_size))0){std::cerrWarning: Failed to set send buffer: strerror(errno)std::endl;}returntrue;}boolUdpClient::Connect(){if(sockfd_0){std::cerrSocket not initializedstd::endl;returnfalse;}// UDP是无连接的这里只是测试与服务器的连通性std::string test_msgCONNECT_TEST;std::string response;if(SendAndReceive(test_msg,response,3000)){std::coutSuccessfully connected to serverstd::endl;std::coutServer response: responsestd::endl;is_connected_true;returntrue;}else{std::cerrFailed to connect to serverstd::endl;returnfalse;}}3.3 发送和接收数据boolUdpClient::Send(conststd::stringdata){returnSend(data.c_str(),data.length());}boolUdpClient::Send(constvoid*data,size_t len){if(sockfd_0){std::cerrSocket not initializedstd::endl;returnfalse;}if(len0){std::cerrAttempting to send empty datastd::endl;returnfalse;}// 检查数据包大小if(len65507){std::cerrData too large: len bytes (max: 65507)std::endl;returnfalse;}// 发送数据ssize_t sentsendto(sockfd_,data,len,0,(structsockaddr*)server_addr_,sizeof(server_addr_));if(sent0){std::cerrSend failed: strerror(errno)std::endl;returnfalse;}if(static_castsize_t(sent)!len){std::cerrPartial send: sent of len bytesstd::endl;}// 更新统计信息packets_sent_;bytes_sent_sent;std::coutSent sent bytes to server_ip_:server_port_std::endl;returntrue;}boolUdpClient::Receive(std::stringdata,inttimeout_ms){if(sockfd_0){std::cerrSocket not initializedstd::endl;returnfalse;}// 设置接收超时if(timeout_ms0){structtimevaltv;tv.tv_sectimeout_ms/1000;tv.tv_usec(timeout_ms%1000)*1000;setsockopt(sockfd_,SOL_SOCKET,SO_RCVTIMEO,tv,sizeof(tv));}// 接收缓冲区charbuffer[65536];structsockaddr_infrom_addr;socklen_t addr_lensizeof(from_addr);// 接收数据ssize_t recv_lenrecvfrom(sockfd_,buffer,sizeof(buffer)-1,0,(structsockaddr*)from_addr,addr_len);if(recv_len0){if(errnoEAGAIN||errnoEWOULDBLOCK){std::coutReceive timeoutstd::endl;}else{std::cerrReceive failed: strerror(errno)std::endl;}returnfalse;}// 确保字符串以null结尾buffer[recv_len]\0;data.assign(buffer,recv_len);// 获取发送者信息charfrom_ip[INET_ADDRSTRLEN];inet_ntop(AF_INET,from_addr.sin_addr,from_ip,sizeof(from_ip));uint16_tfrom_portntohs(from_addr.sin_port);// 更新统计信息packets_received_;bytes_received_recv_len;std::coutReceived recv_len bytes from from_ip:from_portstd::endl;returntrue;}boolUdpClient::SendAndReceive(conststd::stringsend_data,std::stringrecv_data,inttimeout_ms){// 发送数据if(!Send(send_data)){returnfalse;}// 接收响应if(!Receive(recv_data,timeout_ms)){returnfalse;}returntrue;}3.4 交互模式和性能测试voidUdpClient::RunInteractive(){if(!is_connected_){if(!Connect()){std::cerrCannot start interactive mode: not connectedstd::endl;return;}}is_running_true;std::cout\n UDP Client Interactive Mode \n;std::coutType help for commands, quit to exit\n\n;std::string input;while(is_running_){std::coutudp ;std::getline(std::cin,input);if(input.empty()){continue;}// 处理命令if(inputquit||inputexit){std::coutExiting...std::endl;break;}elseif(inputhelp){ShowHelp();}elseif(inputstatus){PrintStatus();}elseif(inputstats){std::cout\n Statistics \n;std::coutPackets sent: packets_sent_\n;std::coutPackets received: packets_received_\n;std::coutBytes sent: bytes_sent_\n;std::coutBytes received: bytes_received_\n;if(packets_sent_0){std::coutAverage sent size: (bytes_sent_/packets_sent_) bytes\n;}if(packets_received_0){std::coutAverage received size: (bytes_received_/packets_received_) bytes\n;}}elseif(inputreset){ResetStats();std::coutStatistics resetstd::endl;}elseif(inputping){std::string response;if(SendAndReceive(PING,response)){std::coutServer response: responsestd::endl;}}elseif(inputtime){std::string response;if(SendAndReceive(TIME,response)){std::coutServer time: response;}}elseif(input.compare(0,4,echo)0){if(input.length()5){std::string echo_datainput.substr(5);std::string response;if(SendAndReceive(ECHO echo_data,response)){std::coutEcho: responsestd::endl;}}else{std::coutUsage: echo messagestd::endl;}}elseif(input.compare(0,4,file)0){// 模拟文件传输std::string filenameinput.length()5?input.substr(5):test.txt;std::coutSimulating file transfer: filenamestd::endl;// 创建模拟文件内容std::string file_content;for(inti0;i100;i){file_contentLine std::to_string(i1): This is test data\n;}// 分块发送constsize_t CHUNK_SIZE1024;size_t total_sent0;intchunk_num1;for(size_t i0;ifile_content.length();iCHUNK_SIZE){size_t chunk_lenstd::min(CHUNK_SIZE,file_content.length()-i);std::string chunkfile_content.substr(i,chunk_len);// 添加块头信息std::string chunk_with_headerFILE_CHUNK std::to_string(chunk_num) chunk;if(Send(chunk_with_header)){total_sentchunk_len;std::coutSent chunk chunk_num (chunk_len bytes)std::endl;chunk_num;// 小延迟usleep(10000);// 10ms}else{std::cerrFailed to send chunk chunk_numstd::endl;break;}}std::coutFile transfer complete: total_sent bytes sentstd::endl;}elseif(inputperftest){RunPerformanceTest();}else{// 默认发送原始消息std::string response;if(SendAndReceive(input,response)){std::coutResponse: responsestd::endl;}}}}voidUdpClient::RunPerformanceTest(intnum_packets,intpacket_size){std::cout\n Performance Test \n;std::coutPackets: num_packets\n;std::coutPacket size: packet_size bytes\n;std::coutTotal data: (num_packets*packet_size/1024.0/1024.0) MB\n\n;// 准备测试数据std::vectorchartest_data(packet_size,X);// 记录开始时间autostart_timestd::chrono::high_resolution_clock::now();// 发送测试数据包intsuccessful_sends0;for(inti0;inum_packets;i){// 在数据中包含序列号和时间戳uint64_tseqi;autotimestampstd::chrono::high_resolution_clock::now();uint64_ttimestamp_nsstd::chrono::duration_caststd::chrono::nanoseconds(timestamp.time_since_epoch()).count();// 将序列号和时间戳复制到数据开始处memcpy(test_data.data(),seq,sizeof(seq));memcpy(test_data.data()sizeof(seq),timestamp_ns,sizeof(timestamp_ns));if(Send(test_data.data(),packet_size)){successful_sends;}// 每100个包打印进度if((i1)%1000){std::coutSent (i1) packets...std::endl;}// 控制发送速率1000 packets/secondusleep(1000);}// 记录结束时间autoend_timestd::chrono::high_resolution_clock::now();autodurationstd::chrono::duration_caststd::chrono::milliseconds(end_time-start_time);// 接收响应可选std::cout\nWaiting for responses...std::endl;intresponses_received0;autoreceive_startstd::chrono::high_resolution_clock::now();// 设置短超时接收剩余响应structtimevaltv;tv.tv_sec2;tv.tv_usec0;setsockopt(sockfd_,SOL_SOCKET,SO_RCVTIMEO,tv,sizeof(tv));charbuffer[65536];while(true){ssize_t recv_lenrecvfrom(sockfd_,buffer,sizeof(buffer)-1,0,NULL,NULL);if(recv_len0){responses_received;// 解析响应中的序列号if(recv_lensizeof(uint64_t)){uint64_tseq;memcpy(seq,buffer,sizeof(seq));// 可以在这里计算往返时间等}}else{break;// 超时}}autoreceive_endstd::chrono::high_resolution_clock::now();autoreceive_durationstd::chrono::duration_caststd::chrono::milliseconds(receive_end-receive_start);// 输出结果std::cout\n Test Results \n;std::coutPackets sent: successful_sends/num_packets\n;std::coutResponses received: responses_received\n;std::coutSend duration: duration.count() ms\n;std::coutReceive duration: receive_duration.count() ms\n;if(duration.count()0){doublesend_rate(successful_sends*1000.0)/duration.count();doublethroughput(successful_sends*packet_size*8.0)/(duration.count()*1000.0);// Mbpsstd::coutSend rate: send_rate packets/second\n;std::coutThroughput: throughput Mbps\n;}if(responses_received0){doubleresponse_rate(responses_received*1000.0)/receive_duration.count();std::coutResponse rate: response_rate packets/second\n;}doubleloss_rate0;if(successful_sends0){loss_rate(1.0-(responses_received/(double)successful_sends))*100.0;std::coutPacket loss rate: std::fixedstd::setprecision(2)loss_rate%\n;}}voidUdpClient::ShowHelp()const{std::cout\nAvailable commands:\n;std::cout help Show this help message\n;std::cout quit, exit Exit the client\n;std::cout status Show connection status\n;std::cout stats Show statistics\n;std::cout reset Reset statistics\n;std::cout ping Send ping to server\n;std::cout time Get server time\n;std::cout echo message Echo message to server\n;std::cout file [name] Simulate file transfer\n;std::cout perftest Run performance test\n;std::cout any text Send custom message\n;}voidUdpClient::PrintStatus()const{std::cout\n Client Status \n;std::coutServer: server_ip_:server_port_\n;std::coutSocket: (sockfd_0?OK:Not initialized)\n;std::coutConnected: (is_connected_?Yes:No)\n;std::coutRunning: (is_running_?Yes:No)\n;}voidUdpClient::GetStats(uint64_tsent_packets,uint64_treceived_packets,uint64_tsent_bytes,uint64_treceived_bytes)const{sent_packetspackets_sent_;received_packetspackets_received_;sent_bytesbytes_sent_;received_bytesbytes_received_;}voidUdpClient::ResetStats(){packets_sent_0;packets_received_0;bytes_sent_0;bytes_received_0;}voidUdpClient::Disconnect(){if(sockfd_0){// 发送断开连接消息std::string disconnect_msgDISCONNECT;Send(disconnect_msg);// 关闭套接字close(sockfd_);sockfd_-1;std::coutDisconnected from serverstd::endl;}is_connected_false;is_running_false;}// 客户端主程序intmain(intargc,char*argv[]){std::string server_ip127.0.0.1;intserver_port8080;// 解析命令行参数for(inti1;iargc;i){std::string argargv[i];if(arg-s||arg--server){if(i1argc){server_ipargv[i];}}elseif(arg-p||arg--port){if(i1argc){server_portstd::atoi(argv[i]);}}elseif(arg-h||arg--help){std::coutUDP Client Usage:\n;std::cout -s, --server IP Server IP address (default: 127.0.0.1)\n;std::cout -p, --port PORT Server port (default: 8080)\n;std::cout -t, --test Run performance test\n;std::cout -i, --interactive Run in interactive mode\n;std::cout -h, --help Show this help\n;return0;}elseif(arg-t||arg--test){// 性能测试模式UdpClientclient(server_ip,server_port);if(client.Init()client.Connect()){client.RunPerformanceTest();}return0;}elseif(arg-i||arg--interactive){// 交互模式默认}}std::cout UDP Client \n;std::coutConnecting to server_ip:server_port\n\n;UdpClientclient(server_ip,server_port);if(!client.Init()){std::cerrFailed to initialize clientstd::endl;return1;}if(!client.Connect()){std::cerrFailed to connect to serverstd::endl;return1;}// 运行交互模式client.RunInteractive();std::cout\nClient terminatedstd::endl;return0;}四、测试4.1 单元测试// TestUdpServer.cpp#includegtest/gtest.h#includethread#includechrono#includeUdpServer.hpp#includeUdpClient.hclassUdpServerTest:public::testing::Test{protected:voidSetUp()override{// 启动测试服务器test_port_9999;server_std::make_uniqueUdpServer(test_port_);ASSERT_TRUE(server_-Init());// 在后台线程运行服务器server_thread_std::thread([this](){server_-Run();});// 等待服务器启动std::this_thread::sleep_for(std::chrono::milliseconds(100));}voidTearDown()override{if(server_){server_-Stop();}if(server_thread_.joinable()){server_thread_.join();}}inttest_port_;std::unique_ptrUdpServerserver_;std::thread server_thread_;};TEST_F(UdpServerTest,BasicEcho){UdpClientclient(127.0.0.1,test_port_);ASSERT_TRUE(client.Init());std::string send_dataHello, Server!;std::string recv_data;EXPECT_TRUE(client.SendAndReceive(send_data,recv_data));EXPECT_NE(recv_data.find(Server received),std::string::npos);EXPECT_NE(recv_data.find(send_data),std::string::npos);}TEST_F(UdpServerTest,MultipleClients){constintNUM_CLIENTS5;std::vectorstd::unique_ptrUdpClientclients;std::vectorstd::threadclient_threads;for(inti0;iNUM_CLIENTS;i){autoclientstd::make_uniqueUdpClient(127.0.0.1,test_port_);ASSERT_TRUE(client-Init());clients.push_back(std::move(client));}// 并发发送消息for(inti0;iNUM_CLIENTS;i){client_threads.emplace_back([clients,i](){std::string send_dataMessage from client std::to_string(i);std::string recv_data;EXPECT_TRUE(clients[i]-SendAndReceive(send_data,recv_data,3000));});}// 等待所有线程完成for(autothread:client_threads){thread.join();}}TEST_F(UdpServerTest,LargeData){UdpClientclient(127.0.0.1,test_port_);ASSERT_TRUE(client.Init());// 发送较大数据小于64KBstd::stringlarge_data(50000,X);// 50KBstd::string recv_data;EXPECT_TRUE(client.SendAndReceive(large_data,recv_data,5000));EXPECT_GT(recv_data.size(),large_data.size());}TEST_F(UdpServerTest,Performance){UdpClientclient(127.0.0.1,test_port_);ASSERT_TRUE(client.Init());constintNUM_PACKETS100;constintPACKET_SIZE1400;// 避免分片autostart_timestd::chrono::high_resolution_clock::now();intsuccess_count0;for(inti0;iNUM_PACKETS;i){std::stringdata(PACKET_SIZE,A(i%26));std::string response;if(client.SendAndReceive(data,response,1000)){success_count;}std::this_thread::sleep_for(std::chrono::milliseconds(10));}autoend_timestd::chrono::high_resolution_clock::now();autodurationstd::chrono::duration_caststd::chrono::milliseconds(end_time-start_time);std::cout\nPerformance Test Results:\n;std::coutSuccessful exchanges: success_count/NUM_PACKETS\n;std::coutTotal time: duration.count() ms\n;std::coutAverage RTT: (duration.count()/(double)success_count) ms\n;EXPECT_GT(success_count,NUM_PACKETS*0.9);// 90%成功率}intmain(intargc,char**argv){::testing::InitGoogleTest(argc,argv);returnRUN_ALL_TESTS();}4.2 集成测试// IntegrationTest.cpp#includeiostream#includethread#includevector#includeatomic#includeAdvancedUdpServer.hpp#includeUdpClient.hclassIntegrationTest{private:std::unique_ptrAdvancedUdpServerserver_;std::thread server_thread_;intserver_port_;public:IntegrationTest(intport8888,intworkers4):server_port_(port){// 启动高性能服务器server_std::make_uniqueAdvancedUdpServer(port,workers);server_-SetBufferSize(65536);server_-SetTimeout(1,0);if(!server_-Init()){throwstd::runtime_error(Failed to initialize server);}// 在后台运行服务器server_thread_std::thread([this](){server_-Run();});// 等待服务器启动std::this_thread::sleep_for(std::chrono::milliseconds(200));std::coutTest server started on port portstd::endl;}~IntegrationTest(){if(server_){server_-Stop();}if(server_thread_.joinable()){server_thread_.join();}std::coutTest server stoppedstd::endl;}voidRunLoadTest(intnum_clients,intmessages_per_client){std::cout\n Load Test \n;std::coutClients: num_clients\n;std::coutMessages per client: messages_per_client\n;std::vectorstd::threadclient_threads;std::atomicinttotal_success{0};std::atomicinttotal_failures{0};autostart_timestd::chrono::high_resolution_clock::now();// 创建客户端线程for(intclient_id0;client_idnum_clients;client_id){client_threads.emplace_back([this,client_id,messages_per_client,total_success,total_failures](){UdpClientclient(127.0.0.1,server_port_);if(!client.Init()){total_failuresmessages_per_client;return;}intlocal_success0;intlocal_failures0;for(intmsg_num0;msg_nummessages_per_client;msg_num){std::string messageClientstd::to_string(client_id)_Msgstd::to_string(msg_num);std::string response;if(client.SendAndReceive(message,response,1000)){local_success;// 验证响应包含原始消息if(response.find(message)std::string::npos){std::cerrWarning: Invalid response from serverstd::endl;}}else{local_failures;}// 小延迟避免拥塞std::this_thread::sleep_for(std::chrono::milliseconds(10));}total_successlocal_success;total_failureslocal_failures;std::coutClient client_id: local_success/messages_per_client successfulstd::endl;});}// 等待所有客户端完成for(autothread:client_threads){thread.join();}autoend_timestd::chrono::high_resolution_clock::now();autodurationstd::chrono::duration_caststd::chrono::milliseconds(end_time-start_time);// 输出结果std::cout\n Load Test Results \n;std::coutTotal messages: (num_clients*messages_per_client)\n;std::coutSuccessful: total_success\n;std::coutFailed: total_failures\n;std::coutSuccess rate: (total_success*100.0/(num_clients*messages_per_client))%\n;std::coutTotal time: duration.count() ms\n;std::coutThroughput: (total_success*1000.0/duration.count()) messages/second\n;// 验证至少95%成功率doublesuccess_ratetotal_success*100.0/(num_clients*messages_per_client);if(success_rate95.0){std::cout\n✓ Load test PASSEDstd::endl;}else{std::cout\n✗ Load test FAILED (success rate below 95%)std::endl;}}voidRunStressTest(){std::cout\n Stress Test \n;constintNUM_CLIENTS10;constintMESSAGES_PER_CLIENT1000;constintMESSAGE_SIZE1000;// 1KBstd::vectorstd::threadclient_threads;std::atomicuint64_ttotal_bytes_sent{0};std::atomicuint64_ttotal_bytes_received{0};autostart_timestd::chrono::high_resolution_clock::now();for(inti0;iNUM_CLIENTS;i){client_threads.emplace_back([this,i,total_bytes_sent,total_bytes_received](){UdpClientclient(127.0.0.1,server_port_);if(!client.Init()){return;}// 准备大消息std::stringlarge_message(MESSAGE_SIZE,A(i%26));uint64_tclient_bytes_sent0;uint64_tclient_bytes_received0;for(intj0;jMESSAGES_PER_CLIENT;j){// 修改消息内容large_message[0]0(j%10);std::string response;if(client.SendAndReceive(large_message,response,500)){client_bytes_sentlarge_message.size();client_bytes_receivedresponse.size();}// 更短的延迟以增加压力if(j%1000){std::this_thread::sleep_for(std::chrono::microseconds(100));}}total_bytes_sentclient_bytes_sent;total_bytes_receivedclient_bytes_received;std::coutStress client i completedstd::endl;});}for(autothread:client_threads){thread.join();}autoend_timestd::chrono::high_resolution_clock::now();autodurationstd::chrono::duration_caststd::chrono::milliseconds(end_time-start_time);std::cout\n Stress Test Results \n;std::coutTotal data sent: (total_bytes_sent/1024.0/1024.0) MB\n;std::coutTotal data received: (total_bytes_received/1024.0/1024.0) MB\n;std::coutTotal time: duration.count() ms\n;if(duration.count()0){doublesend_throughput(total_bytes_sent*8.0)/(duration.count()*1000.0);// Mbpsdoublereceive_throughput(total_bytes_received*8.0)/(duration.count()*1000.0);// Mbpsstd::coutSend throughput: send_throughput Mbps\n;std::coutReceive throughput: receive_throughput Mbps\n;std::coutTotal throughput: (send_throughputreceive_throughput) Mbps\n;}if(total_bytes_sent0){std::cout\n✓ Stress test completed successfullystd::endl;}}};intmain(){try{std::cout UDP System Integration Test \n\n;IntegrationTesttest(8888,4);// 运行负载测试test.RunLoadTest(5,100);// 运行压力测试test.RunStressTest();std::cout\n All tests completed \n;}catch(conststd::exceptione){std::cerrTest failed: e.what()std::endl;return1;}return0;}4.3 网络测试工具// NetworkTestTool.cpp#includeiostream#includeiomanip#includevector#includemap#includecmath#includeUdpClient.hclassNetworkTestTool{private:std::string server_ip_;intserver_port_;public:NetworkTestTool(conststd::stringip,intport):server_ip_(ip),server_port_(port){}voidRunLatencyTest(intnum_packets100){std::cout\n Latency Test \n;std::coutServer: server_ip_:server_port_\n;std::coutPackets: num_packets\n\n;UdpClientclient(server_ip_,server_port_);if(!client.Init()){std::cerrFailed to initialize clientstd::endl;return;}std::vectordoublelatencies;intsuccessful_packets0;for(inti0;inum_packets;i){// 准备包含时间戳的消息autosend_timestd::chrono::high_resolution_clock::now();uint64_tsend_nsstd::chrono::duration_caststd::chrono::nanoseconds(send_time.time_since_epoch()).count();std::string messagePING_std::to_string(i)_std::to_string(send_ns);std::string response;if(client.SendAndReceive(message,response,1000)){autorecv_timestd::chrono::high_resolution_clock::now();uint64_trecv_nsstd::chrono::duration_caststd::chrono::nanoseconds(recv_time.time_since_epoch()).count();// 计算往返时间doublertt_nsstatic_castdouble(recv_ns-send_ns);doublertt_msrtt_ns/1000000.0;latencies.push_back(rtt_ms);successful_packets;if((i1)%100){std::coutSent (i1) packets...std::endl;}}else{std::coutPacket i loststd::endl;}// 等待以避免拥塞std::this_thread::sleep_for(std::chrono::milliseconds(100));}// 计算统计信息if(!latencies.empty()){doublesum0;doublemin_latencylatencies[0];doublemax_latencylatencies[0];for(doublelatency:latencies){sumlatency;min_latencystd::min(min_latency,latency);max_latencystd::max(max_latency,latency);}doubleaveragesum/latencies.size();// 计算标准差doublevariance0;for(doublelatency:latencies){variance(latency-average)*(latency-average);}variance/latencies.size();doublestddevstd::sqrt(variance);// 计算百分位数std::sort(latencies.begin(),latencies.end());doublep50latencies[latencies.size()*0.5];doublep90latencies[latencies.size()*0.9];doublep95latencies[latencies.size()*0.95];doublep99latencies[latencies.size()*0.99];// 输出结果std::cout\n Latency Test Results \n;std::coutPackets sent: num_packets\n;std::coutPackets received: successful_packets\n;std::coutPacket loss: std::fixedstd::setprecision(2)((num_packets-successful_packets)*100.0/num_packets)%\n;std::cout\nLatency statistics (ms):\n;std::cout Minimum: std::fixedstd::setprecision(3)min_latency\n;std::cout Maximum: max_latency\n;std::cout Average: average\n;std::cout Std Dev: stddev\n;std::cout 50th percentile: p50\n;std::cout 90th percentile: p90\n;std::cout 95th percentile: p95\n;std::cout 99th percentile: p99\n;// 显示直方图DisplayHistogram(latencies);}}voidDisplayHistogram(conststd::vectordoubledata){if(data.empty())return;doublemin_val*std::min_element(data.begin(),data.end());doublemax_val*std::max_element(data.begin(),data.end());constintNUM_BINS10;doublebin_width(max_val-min_val)/NUM_BINS;std::vectorintbins(NUM_BINS,0);for(doublevalue:data){intbin_indexstatic_castint((value-min_val)/bin_width);if(bin_indexNUM_BINS)bin_index--;// 处理边界情况bins[bin_index];}std::cout\nLatency distribution:\n;for(inti0;iNUM_BINS;i){doublebin_startmin_vali*bin_width;doublebin_endbin_startbin_width;std::coutstd::fixedstd::setprecision(1) std::setw(6)bin_start - std::setw(6)bin_end ms: std::string(bins[i]*50/data.size(),#) (bins[i])\n;}}voidRunBandwidthTest(intduration_sec10,intpacket_size1400){std::cout\n Bandwidth Test \n;std::coutDuration: duration_sec seconds\n;std::coutPacket size: packet_size bytes\n\n;UdpClientclient(server_ip_,server_port_);if(!client.Init()){std::cerrFailed to initialize clientstd::endl;return;}std::vectorcharpacket_data(packet_size,B);autostart_timestd::chrono::steady_clock::now();autoend_timestart_timestd::chrono::seconds(duration_sec);uint64_ttotal_packets0;uint64_ttotal_bytes0;uint64_tsuccessful_responses0;std::coutTesting bandwidth...\n;while(std::chrono::steady_clock::now()end_time){// 发送数据包if(client.Send(packet_data.data(),packet_size)){total_packets;total_bytespacket_size;}// 尝试接收响应非阻塞std::string response;if(client.Receive(response,10)){// 10ms超时successful_responses;}// 控制发送速率约1000 packets/secondstd::this_thread::sleep_for(std::chrono::microseconds(900));}autoactual_endstd::chrono::steady_clock::now();autoactual_durationstd::chrono::duration_caststd::chrono::milliseconds(actual_end-start_time);// 输出结果std::cout\n Bandwidth Test Results \n;std::coutActual duration: actual_duration.count() ms\n;std::coutPackets sent: total_packets\n;std::coutTotal data sent: (total_bytes/1024.0/1024.0) MB\n;std::coutResponses received: successful_responses\n;if(actual_duration.count()0){doublepackets_per_sectotal_packets*1000.0/actual_duration.count();doublebandwidth_mbps(total_bytes*8.0)/(actual_duration.count()*1000.0);std::coutSend rate: packets_per_sec packets/second\n;std::coutBandwidth: bandwidth_mbps Mbps\n;std::coutResponse rate: (successful_responses*1000.0/actual_duration.count()) packets/second\n;}doubleloss_rate0;if(total_packets0){loss_rate(1.0-(successful_responses/(double)total_packets))*100.0;std::coutEstimated loss rate: std::fixedstd::setprecision(2)loss_rate%\n;}}};intmain(intargc,char*argv[]){std::string server_ip127.0.0.1;intserver_port8080;std::string test_typelatency;// 解析命令行参数for(inti1;iargc;i){std::string argargv[i];if(arg-s||arg--server){if(i1argc)server_ipargv[i];}elseif(arg-p||arg--port){if(i1argc)server_portstd::atoi(argv[i]);}elseif(arg-t||arg--test){if(i1argc)test_typeargv[i];}elseif(arg-h||arg--help){std::coutNetwork Test Tool\n\n;std::coutUsage: argv[0] [options]\n\n;std::coutOptions:\n;std::cout -s, --server IP Server IP address\n;std::cout -p, --port PORT Server port\n;std::cout -t, --test TYPE Test type (latency|bandwidth)\n;std::cout -h, --help Show this help\n;return0;}}NetworkTestTooltester(server_ip,server_port);if(test_typelatency){tester.RunLatencyTest();}elseif(test_typebandwidth){tester.RunBandwidthTest();}else{std::cerrUnknown test type: test_typestd::endl;std::cerrAvailable types: latency, bandwidthstd::endl;return1;}return0;}五、源代码5.1 Log.hpp - 日志系统#ifndefLOG_HPP#defineLOG_HPP#includeiostream#includefstream#includestring#includesstream#includeiomanip#includectime#includemutex#includememory// 日志级别enumclassLogLevel{DEBUG,INFO,WARN,ERROR,FATAL};classLogger{private:staticstd::shared_ptrLoggerinstance_;std::ofstream log_file_;LogLevel min_level_;std::mutex log_mutex_;boolconsole_output_;// 私有构造函数Logger():min_level_(LogLevel::INFO),console_output_(true){}public:// 删除拷贝构造函数和赋值运算符Logger(constLogger)delete;Loggeroperator(constLogger)delete;// 获取单例实例staticLoggerInstance(){staticstd::shared_ptrLoggerinstance(newLogger());return*instance;}// 初始化日志系统boolInit(conststd::stringfilename,LogLevel min_levelLogLevel::INFO,boolconsoletrue){std::lock_guardstd::mutexlock(log_mutex_);min_level_min_level;console_output_console;if(!filename.empty()){log_file_.open(filename,std::ios::app);if(!log_file_.is_open()){std::cerrFailed to open log file: filenamestd::endl;returnfalse;}}returntrue;}// 设置日志级别voidSetLevel(LogLevel level){std::lock_guardstd::mutexlock(log_mutex_);min_level_level;}// 启用/禁用控制台输出voidEnableConsole(boolenable){std::lock_guardstd::mutexlock(log_mutex_);console_output_enable;}// 记录日志voidLog(LogLevel level,conststd::stringmessage,constchar*filenullptr,intline0){if(levelmin_level_){return;}std::lock_guardstd::mutexlock(log_mutex_);// 获取当前时间autonowstd::chrono::system_clock::now();autonow_timestd::chrono::system_clock::to_time_t(now);autonow_msstd::chrono::duration_caststd::chrono::milliseconds(now.time_since_epoch())%1000;// 格式化时间std::tm*tm_infostd::localtime(now_time);chartime_buffer[80];std::strftime(time_buffer,sizeof(time_buffer),%Y-%m-%d %H:%M:%S,tm_info);// 日志级别字符串constchar*level_str;switch(level){caseLogLevel::DEBUG:level_strDEBUG;break;caseLogLevel::INFO:level_strINFO;break;caseLogLevel::WARN:level_strWARN;break;caseLogLevel::ERROR:level_strERROR;break;caseLogLevel::FATAL:level_strFATAL;break;}// 构建日志消息std::stringstream ss;ss[time_buffer.std::setfill(0)std::setw(3)now_ms.count()] [level_str] ;if(file!nullptr){ss[file:line] ;}ssmessage;std::string log_messagess.str();// 输出到控制台if(console_output_){std::ostreamstream(levelLogLevel::WARN)?std::cerr:std::cout;streamlog_messagestd::endl;if(levelLogLevel::FATAL){streamFatal error, terminating...std::endl;}}// 输出到文件if(log_file_.is_open()){log_file_log_messagestd::endl;log_file_.flush();if(levelLogLevel::FATAL){log_file_Fatal error, terminating...std::endl;log_file_.flush();}}// 如果是致命错误终止程序if(levelLogLevel::FATAL){std::exit(EXIT_FAILURE);}}// 关闭日志voidClose(){std::lock_guardstd::mutexlock(log_mutex_);if(log_file_.is_open()){log_file_.close();}}~Logger(){Close();}};// 日志宏#defineLOG_DEBUG(msg)Logger::Instance().Log(LogLevel::DEBUG,msg,__FILE__,__LINE__)#defineLOG_INFO(msg)Logger::Instance().Log(LogLevel::INFO,msg,__FILE__,__LINE__)#defineLOG_WARN(msg)Logger::Instance().Log(LogLevel::WARN,msg,__FILE__,__LINE__)#defineLOG_ERROR(msg)Logger::Instance().Log(LogLevel::ERROR,msg,__FILE__,__LINE__)#defineLOG_FATAL(msg)Logger::Instance().Log(LogLevel::FATAL,msg,__FILE__,__LINE__)#endif// LOG_HPP5.2 Makefile - 构建系统# Makefile for UDP Network System # Compiler and flags CXX g CXXFLAGS -stdc11 -Wall -Wextra -O2 -pthread DEBUG_FLAGS -g -DDEBUG RELEASE_FLAGS -O3 -DNDEBUG # Directories SRC_DIR src OBJ_DIR obj BIN_DIR bin INC_DIR include # Source files SERVER_SRCS $(SRC_DIR)/UdpServer.cpp $(SRC_DIR)/Main.cpp $(SRC_DIR)/Log.cpp CLIENT_SRCS $(SRC_DIR)/UdpClient.cpp TEST_SRCS $(SRC_DIR)/TestUdpServer.cpp INTEGRATION_SRCS $(SRC_DIR)/IntegrationTest.cpp NETTEST_SRCS $(SRC_DIR)/NetworkTestTool.cpp # Object files SERVER_OBJS $(patsubst $(SRC_DIR)/%.cpp,$(OBJ_DIR)/%.o,$(SERVER_SRCS)) CLIENT_OBJS $(patsubst $(SRC_DIR)/%.cpp,$(OBJ_DIR)/%.o,$(CLIENT_SRCS)) TEST_OBJS $(patsubst $(SRC_DIR)/%.cpp,$(OBJ_DIR)/%.o,$(TEST_SRCS)) INTEGRATION_OBJS $(patsubst $(SRC_DIR)/%.cpp,$(OBJ_DIR)/%.o,$(INTEGRATION_SRCS)) NETTEST_OBJS $(patsubst $(SRC_DIR)/%.cpp,$(OBJ_DIR)/%.o,$(NETTEST_SRCS)) # Executables SERVER_EXE $(BIN_DIR)/udp_server CLIENT_EXE $(BIN_DIR)/udp_client TEST_EXE $(BIN_DIR)/test_server INTEGRATION_EXE $(BIN_DIR)/integration_test NETTEST_EXE $(BIN_DIR)/network_test # Include paths INCLUDES -I$(INC_DIR) # Libraries LIBS -lpthread TEST_LIBS $(LIBS) -lgtest -lgtest_main # Default target all: directories server client # Create directories directories: mkdir -p $(OBJ_DIR) $(BIN_DIR) # Server build server: $(SERVER_EXE) $(SERVER_EXE): $(SERVER_OBJS) $(CXX) $(CXXFLAGS) $(INCLUDES) $^ -o $ $(LIBS) # Client build client: $(CLIENT_EXE) $(CLIENT_EXE): $(CLIENT_OBJS) $(CXX) $(CXXFLAGS) $(INCLUDES) $^ -o $ $(LIBS) # Test build test: $(TEST_EXE) $(TEST_EXE): $(TEST_OBJS) $(CXX) $(CXXFLAGS) $(INCLUDES) $^ -o $ $(TEST_LIBS) # Integration test build integration: $(INTEGRATION_EXE) $(INTEGRATION_EXE): $(INTEGRATION_OBJS) $(CXX) $(CXXFLAGS) $(INCLUDES) $^ -o $ $(LIBS) # Network test tool build nettest: $(NETTEST_EXE) $(NETTEST_EXE): $(NETTEST_OBJS) $(CXX) $(CXXFLAGS) $(INCLUDES) $^ -o $ $(LIBS) # Compile source files $(OBJ_DIR)/%.o: $(SRC_DIR)/%.cpp $(CXX) $(CXXFLAGS) $(INCLUDES) -c $ -o $ # Debug build debug: CXXFLAGS $(DEBUG_FLAGS) debug: all # Release build release: CXXFLAGS $(RELEASE_FLAGS) release: all # Static analysis with cppcheck check: cppcheck --enableall --suppressmissingIncludeSystem $(SRC_DIR) $(INC_DIR) # Run tests run-test: test $(TEST_EXE) run-integration: integration $(INTEGRATION_EXE) # Clean build files clean: rm -rf $(OBJ_DIR) $(BIN_DIR) rm -f *.log # Install system-wide (requires root) install: release cp $(SERVER_EXE) /usr/local/bin/udp_server cp $(CLIENT_EXE) /usr/local/bin/udp_client chmod x /usr/local/bin/udp_server /usr/local/bin/udp_client # Uninstall uninstall: rm -f /usr/local/bin/udp_server /usr/local/bin/udp_client # Run server run-server: server $(SERVER_EXE) -p 8080 # Run client run-client: client $(CLIENT_EXE) -s 127.0.0.1 -p 8080 # Run network test run-nettest: nettest $(NETTEST_EXE) -s 127.0.0.1 -p 8080 -t latency # Generate documentation doc: doxygen Doxyfile # Help help: echo Available targets: echo all - Build server and client (default) echo server - Build server only echo client - Build client only echo test - Build and run unit tests echo integration - Build integration tests echo nettest - Build network test tool echo debug - Build with debug flags echo release - Build with release flags echo check - Run static analysis echo run-test - Run unit tests echo run-integration - Run integration tests echo clean - Remove build files echo install - Install system-wide echo uninstall - Uninstall echo run-server - Run server on port 8080 echo run-client - Run client connecting to localhost:8080 echo run-nettest - Run network latency test echo doc - Generate documentation echo help - Show this help .PHONY: all directories server client test integration nettest debug release \ check run-test run-integration clean install uninstall run-server \ run-client run-nettest doc help5.3 完整的UdpServer.hpp#ifndefUDPSERVER_HPP#defineUDPSERVER_HPP#includeiostream#includestring#includecstring#includecstdlib#includeunistd.h#includearpa/inet.h#includesys/socket.h#includesys/types.h#includenetinet/in.h#includethread#includevector#includememory#includeatomic#includefunctional#includequeue#includemutex#includecondition_variable#includeLog.hppclassUdpServer{protected:intport_;// 服务器端口intsockfd_;// 套接字描述符std::atomicboolis_running_;// 服务器运行状态structsockaddr_inserver_addr_;// 服务器地址结构structsockaddr_inclient_addr_;// 客户端地址结构socklen_t client_addr_len_;// 客户端地址长度// 服务器配置参数size_t buffer_size_;// 缓冲区大小inttimeout_sec_;// 接收超时时间(秒)inttimeout_usec_;// 接收超时时间(微秒)boolreuse_addr_;// 是否重用地址public:// 构造函数explicitUdpServer(intport8080);// 析构函数virtual~UdpServer();// 禁止拷贝构造和赋值UdpServer(constUdpServer)delete;UdpServeroperator(constUdpServer)delete;// 初始化服务器virtualboolInit();// 运行服务器virtualvoidRun();// 停止服务器virtualvoidStop();// 设置配置参数voidSetBufferSize(size_t size){buffer_size_size;}voidSetTimeout(intsec,intusec0){timeout_sec_sec;timeout_usec_usec;}voidSetReuseAddr(boolreuse){reuse_addr_reuse;}// 获取服务器信息intGetPort()const{returnport_;}boolIsRunning()const{returnis_running_;}protected:// 创建套接字virtualboolCreateSocket();// 绑定地址virtualboolBindAddress();// 设置套接字选项virtualboolSetSocketOptions();// 处理接收到的数据virtualvoidProcessData(constchar*data,ssize_t len,conststructsockaddr_inclient_addr);// 发送响应virtualboolSendResponse(constchar*data,ssize_t len,conststructsockaddr_inclient_addr);// 清理资源virtualvoidCleanup();};// 高级UDP服务器带线程池classAdvancedUdpServer:publicUdpServer{private:std::vectorstd::threadworker_threads_;std::atomicintthread_count_;intmax_workers_;// 线程池和工作队列structTask{std::vectorchardata;structsockaddr_inclient_addr;time_t receive_time;Task(conststd::vectorchard,conststructsockaddr_inaddr):data(d),client_addr(addr),receive_time(time(nullptr)){}};std::queueTasktask_queue_;std::mutex queue_mutex_;std::condition_variable queue_cv_;std::atomicboolworkers_running_;public:AdvancedUdpServer(intport8080,intmax_workers4);~AdvancedUdpServer()override;boolInit()override;voidRun()override;voidStop()override;// 获取线程池状态intGetActiveWorkers()const{returnthread_count_;}size_tGetQueueSize()const{returntask_queue_.size();}private:voidWorkerThread(intthread_id);voidProcessTask(constTasktask,intthread_id);// 重写基类方法boolSetSocketOptions()override;voidProcessData(constchar*data,ssize_t len,conststructsockaddr_inclient_addr)override;// 任务调度voidAddTask(conststd::vectorchardata,conststructsockaddr_inclient_addr);};#endif// UDPSERVER_HPP5.4 完整的Main.cpp#includeiostream#includecsignal#includecstdlib#includememory#includegetopt.h#includeUdpServer.hpp#includeAdvancedUdpServer.hpp// 全局服务器指针用于信号处理std::unique_ptrUdpServerg_server;// 信号处理函数voidSignalHandler(intsignal){std::cout\nReceived signal signal, shutting down...std::endl;if(g_server){g_server-Stop();}}// 显示使用帮助voidShowUsage(constchar*program_name){std::coutUDP Server v1.0 - High Performance UDP Server Implementation\n;std::coutBuild Date: __DATE__ __TIME__\n\n;std::coutUsage: program_name [options]\n\n;std::coutOptions:\n;std::cout -p, --port PORT Server port (default: 8080)\n;std::cout -b, --buffer SIZE Buffer size in bytes (default: 4096)\n;std::cout -t, --timeout SEC Receive timeout in seconds (default: 5)\n;std::cout -w, --workers NUM Number of worker threads (default: 1)\n;std::cout -a, --advanced Use advanced server with thread pool\n;std::cout -r, --no-reuse Disable address reuse\n;std::cout -v, --verbose Enable verbose logging\n;std::cout -d, --daemon Run as daemon\n;std::cout -c, --config FILE Load configuration from file\n;std::cout -h, --help Show this help message\n;std::cout\nExamples:\n;std::cout program_name -p 9000 -b 8192\n;std::cout program_name --port 8080 --workers 4 --advanced\n;std::cout program_name --daemon --config /etc/udp-server.conf\n;}// 服务器配置结构structServerConfig{intport8080;size_t buffer_size4096;inttimeout_sec5;inttimeout_usec0;intworkers1;booladvancedfalse;boolreuse_addrtrue;booldaemonfalse;boolverbosefalse;std::string config_file;std::string log_fileudp_server.log;LogLevel log_levelLogLevel::INFO;};// 解析命令行参数ServerConfigParseArguments(intargc,char*argv[]){ServerConfig config;structoptionlong_options[]{{port,required_argument,0,p},{buffer,required_argument,0,b},{timeout,required_argument,0,t},{workers,required_argument,0,w},{advanced,no_argument,0,a},{no-reuse,no_argument,0,r},{verbose,no_argument,0,v},{daemon,no_argument,0,d},{config,required_argument,0,c},{help,no_argument,0,h},{0,0,0,0}};intopt;intoption_index0;while((optgetopt_long(argc,argv,p:b:t:w:arvdc:h,long_options,option_index))!-1){switch(opt){casep:config.portstd::atoi(optarg);if(config.port0||config.port65535){std::cerrError: Port must be between 1 and 65535std::endl;exit(EXIT_FAILURE);}break;caseb:config.buffer_sizestd::atoi(optarg);if(config.buffer_size1024||config.buffer_size65536){std::cerrError: Buffer size must be between 1024 and 65536std::endl;exit(EXIT_FAILURE);}break;caset:config.timeout_secstd::atoi(optarg);if(config.timeout_sec0){std::cerrError: Timeout must be non-negativestd::endl;exit(EXIT_FAILURE);}break;casew:config.workersstd::atoi(optarg);if(config.workers1||config.workers32){std::cerrError: Number of workers must be between 1 and 32std::endl;exit(EXIT_FAILURE);}break;casea:config.advancedtrue;break;caser:config.reuse_addrfalse;break;casev:config.verbosetrue;config.log_levelLogLevel::DEBUG;break;cased:config.daemontrue;break;casec:config.config_fileoptarg;// 这里可以添加从配置文件加载配置的逻辑break;caseh:ShowUsage(argv[0]);exit(EXIT_SUCCESS);default:std::cerrError: Unknown optionstd::endl;ShowUsage(argv[0]);exit(EXIT_FAILURE);}}returnconfig;}// 守护进程化voidDaemonize(){pid_t pidfork();if(pid0){std::cerrFailed to fork daemon: strerror(errno)std::endl;exit(EXIT_FAILURE);}if(pid0){// 父进程退出exit(EXIT_SUCCESS);}// 子进程继续umask(0);pid_t sidsetsid();if(sid0){std::cerrFailed to create new session: strerror(errno)std::endl;exit(EXIT_FAILURE);}if((chdir(/))0){std::cerrFailed to change directory: strerror(errno)std::endl;exit(EXIT_FAILURE);}// 关闭标准文件描述符close(STDIN_FILENO);close(STDOUT_FILENO);close(STDERR_FILENO);// 重定向到/dev/nullopen(/dev/null,O_RDONLY);open(/dev/null,O_WRONLY);open(/dev/null,O_RDWR);}intmain(intargc,char*argv[]){// 解析命令行参数ServerConfig configParseArguments(argc,argv);// 如果需要转换为守护进程if(config.daemon){Daemonize();}// 注册信号处理signal(SIGINT,SignalHandler);signal(SIGTERM,SignalHandler);signal(SIGPIPE,SIG_IGN);// 忽略管道破裂信号try{if(!config.daemon){std::cout UDP Server Starting \n;std::coutVersion: 1.0\n;std::coutPort: config.port\n;std::coutBuffer size: config.buffer_size bytes\n;std::coutTimeout: config.timeout_sec seconds\n;std::coutWorkers: config.workers\n;std::coutMode: (config.advanced?Advanced (Thread Pool):Basic)\n;std::coutLog file: config.log_file\n;std::coutLog level: (config.verbose?DEBUG:INFO)\n;std::cout\n\n;}// 初始化日志系统Logger::Instance().Init(config.log_file,config.log_level,!config.daemon);LOG_INFO(UDP Server starting...);LOG_INFO(Configuration: port%d, buffer%zu, timeout%d, workers%d, mode%s,config.port,config.buffer_size,config.timeout_sec,config.workers,config.advanced?advanced:basic);// 创建服务器实例if(config.advanced){g_serverstd::make_uniqueAdvancedUdpServer(config.port,config.workers);}else{g_serverstd::make_uniqueUdpServer(config.port);}// 配置服务器g_server-SetBufferSize(config.buffer_size);g_server-SetTimeout(config.timeout_sec,config.timeout_usec);g_server-SetReuseAddr(config.reuse_addr);// 初始化服务器if(!g_server-Init()){LOG_FATAL(Failed to initialize server);returnEXIT_FAILURE;}LOG_INFO(Server initialized successfully);if(!config.daemon){std::coutServer initialized successfully\n;std::coutPress CtrlC to stop the server\n\n;}// 运行服务器g_server-Run();}catch(conststd::exceptione){LOG_ERROR(Exception: %s,e.what());if(!config.daemon){std::cerrException: e.what()std::endl;}returnEXIT_FAILURE;}catch(...){LOG_ERROR(Unknown exception occurred);if(!config.daemon){std::cerrUnknown exception occurredstd::endl;}returnEXIT_FAILURE;}LOG_INFO(Server stopped gracefully);if(!config.daemon){std::cout\nServer stopped gracefullystd::endl;}returnEXIT_SUCCESS;}总结通过本文的详细讲解和代码实现我们完成了一个完整的UDP网络通信系统的设计与实现。这个系统具有以下特点和优势1. 系统架构特点模块化设计服务器和客户端分离职责明确日志系统独立便于维护和扩展配置系统灵活支持命令行和配置文件高性能设计支持多线程处理充分利用多核CPU智能缓冲区管理避免内存碎片异步I/O操作减少等待时间可靠性保障完善的错误处理和异常恢复机制连接状态监控和自动清理详细的日志记录便于问题排查2. 关键技术点套接字编程核心深入理解了socket()、bind()、recvfrom()、sendto()等系统调用掌握了地址转换函数如inet_pton()、inet_ntop()的使用理解了字节序转换的重要性并发处理多线程编程的最佳实践线程安全的队列实现条件变量的正确使用网络优化缓冲区大小的优化配置超时机制的合理设置数据包分片和重组处理3. 实际应用价值教育意义完整的网络编程教学示例良好的编码规范和架构设计示范详细的注释和文档说明实用价值可直接用于实际项目的网络通信模块提供了性能测试和监控工具支持多种运行模式和配置选项扩展性易于添加新的协议支持支持插件式功能扩展良好的接口设计便于二次开发4. 性能优化建议服务器端优化使用epoll或kqueue等I/O多路复用技术处理更多并发连接实现连接池减少连接建立开销使用内存池技术减少内存分配开销客户端优化实现请求合并减少网络包数量添加压缩支持减少数据传输量实现智能重传机制提高可靠性网络优化支持IPv6双栈添加QUIC协议支持实现流量控制和拥塞避免算法5. 安全考虑基础安全输入验证和边界检查缓冲区溢出防护资源限制和配额管理高级安全支持TLS/DTLS加密传输实现身份验证和授权机制添加DoS攻击防护6. 未来发展方向功能增强添加Web管理界面支持集群部署实现负载均衡性能提升支持RDMA高速网络添加GPU加速支持实现零拷贝技术生态系统提供多种语言SDK支持云原生部署集成监控告警系统通过本系统的实现读者不仅能够掌握UDP网络编程的核心技术还能够学习到软件工程中的良好实践包括模块化设计、错误处理、性能优化、测试策略等。这个系统可以作为学习网络编程的绝佳范例也可以作为实际项目的基础框架进行扩展和优化。网络编程是一个既深又广的领域本文只是抛砖引玉。希望读者能够在此基础上继续探索深入研究网络协议的各个层面从应用层到底层实现不断积累经验最终成为网络编程的专家。
版权声明:本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!

个人怎么做贷款网站网页设计作业题目

FontForge终极指南:免费创建专业字体的完整解决方案 【免费下载链接】fontforge Free (libre) font editor for Windows, Mac OS X and GNULinux 项目地址: https://gitcode.com/gh_mirrors/fo/fontforge FontForge是一款功能强大的开源字体编辑器&#xff0…

张小明 2026/1/7 21:51:44 网站建设

胡芦娃app软件下载网站2345网址导航是谷歌吗

2026年,IT行业将告别单点技术探索的“碎片化时代”,迈入“技术融合价值闭环”的全新周期。中国信通院将其定义为“人工智能浪潮下新质生产力加速释放”的关键年,核心特征表现为AI从“内容生成”向“任务执行”跃迁、算力与网络深度协同、物理…

张小明 2026/1/7 21:51:42 网站建设

织梦网站图片怎么修改网站没有备案 合法吗

好的,我们来详细解释一下布隆过滤器。 布隆过滤器的作用 布隆过滤器(Bloom Filter)是一种概率型数据结构,主要用于高效地判断一个元素是否可能存在于某个集合中。其核心作用在于: 快速查询:能在常数时间内 $O(k)$(k为哈希函数个数)判断一个元素是否可能存在于集合。 空…

张小明 2026/1/8 4:07:29 网站建设

兰州市城关区建设局网站深圳航空公司订票电话

索引设计的原则适合索引的列是出现在where子句中的列,或者连接子句中指定的列基数较小的类,索引效果较差,没有必要在此列建立索引使用短索引,如果对长字符串列进行索引,应该指定一个前缀长度,这样能够节省大…

张小明 2026/1/8 4:07:28 网站建设

网站建设方案分析深圳短视频seo哪家好

如何用m3u8下载器轻松保存网页视频:新手完整指南 【免费下载链接】m3u8-downloader m3u8 视频在线提取工具 流媒体下载 m3u8下载 桌面客户端 windows mac 项目地址: https://gitcode.com/gh_mirrors/m3u8/m3u8-downloader 还在为无法保存在线视频而烦恼吗&am…

张小明 2026/1/8 4:07:26 网站建设

网站flash效果wordpress虚拟物品销售

第一章:系统级编程中C与Rust的融合挑战在现代系统级编程实践中,C语言长期占据主导地位,而Rust凭借其内存安全和并发优势正逐步渗透关键基础设施领域。将两者融合使用,既能利用现有C生态,又能引入Rust的安全保障&#x…

张小明 2026/1/8 4:07:24 网站建设