C 仿muduo高并发服务器Socket模块1. 为什么需要封装 SocketLinux 原生 socket API 是一组 C 函数直接使用存在以下问题参数复杂容易出错如sockaddr类型转换、字节序转换。资源管理麻烦fd 需要手动close。错误处理重复每个调用都要判断返回值、打印日志。阻塞/非阻塞、地址重用等选项设置分散。封装成Socket类后提供面向对象的接口语义清晰。利用 RAII 自动关闭 fd需完善析构函数。统一错误日志输出。方便在 Reactor 模型中作为基础组件使用。2. 类定义概览#defineMAX_LISTEN1024classSocket{private:int_sockfd;public:Socket(){}Socket(intfd):_sockfd(fd){}~Socket(){}intFd(){return_sockfd;}boolCreate();boolBind(conststd::stringip,uint16_tport);boolListen(intbacklogMAX_LISTEN);boolConnect(conststd::stringip,uint16_tport);intAccept();ssize_tRecv(void*buf,size_t len,intflag0);ssize_tNonBlockRecv(void*buf,size_t len);ssize_tSend(constvoid*buf,size_t len,intflag0);ssize_tNonBlockSend(void*buf,size_t len);voidClose();boolCreaterServer(uint16_tport,conststd::stringip0.0.0.0,boolblock_flagfalse);boolCreateClient(uint16_tport,conststd::stringip);voidReuseAddress();voidNonBlock();};3. 成员变量与构造/析构int_sockfd;_sockfd套接字文件描述符-1表示无效。Socket():_sockfd(-1){}Socket(intfd):_sockfd(fd){}~Socket(){}析构函数应调用Close()自动关闭 fd当前为空存在资源泄漏风险。改进建议后期我们再加上~Socket(){Close();}4. 核心函数详解4.1Create()创建套接字boolCreate(){_sockfdsocket(AF_INET,SOCK_STREAM,IPPROTO_TCP);if(_sockfd0){ERR_LOG(CREATE SOCKET FAILED!!);returnfalse;}returntrue;}AF_INETIPv4 协议族。SOCK_STREAMTCP 流式套接字。IPPROTO_TCPTCP 协议。成功返回非负 fd失败返回-1。4.2Bind()绑定地址boolBind(conststd::stringip,uint16_tport){structsockaddr_inaddr;addr.sin_familyAF_INET;addr.sin_porthtons(port);// 端口转网络字节序addr.sin_addr.s_addrinet_addr(ip.c_str());// IP 转网络字节序socklen_t lensizeof(structsockaddr_in);intretbind(_sockfd,(structsockaddr*)addr,len);if(ret0){ERR_LOG(BIND ADDRESS FAILED!);returnfalse;}returntrue;}htons主机字节序 → 网络字节序16 位。inet_addr点分十进制 IP → 网络字节序 32 位整数。服务器必须bind客户端通常不需要。4.3Listen()开始监听boolListen(intbacklogMAX_LISTEN){intretlisten(_sockfd,backlog);if(ret0){ERR_LOG(SOCKET LISTEN FAILED!);returnfalse;}returntrue;}backlog已完成连接队列的最大长度默认MAX_LISTEN1024。将主动套接字变为被动监听套接字内核开始接受连接。4.4Connect()客户端发起连接boolConnect(conststd::stringip,uint16_tport){structsockaddr_inaddr;addr.sin_familyAF_INET;addr.sin_porthtons(port);addr.sin_addr.s_addrinet_addr(ip.c_str());socklen_t lensizeof(structsockaddr_in);intretconnect(_sockfd,(structsockaddr*)addr,len);if(ret0){ERR_LOG(CONNECT SERVER FAILED!);returnfalse;}returntrue;}向服务器发起 TCP 连接触发三次握手。阻塞模式下会等待连接完成。4.5Accept()接受新连接intAccept(){intnewfdaccept(_sockfd,NULL,NULL);if(newfd0){ERR_LOG(SOCKET ACCEPT FAILED!);return-1;}returnnewfd;}从已完成连接队列取出一个连接返回新的通信 fd。监听 fd 继续监听新 fd 用于和客户端通信。非阻塞模式下无连接时返回-1errno为EAGAIN。4.6Recv()与NonBlockRecv()ssize_tRecv(void*buf,size_t len,intflag0){ssize_t retrecv(_sockfd,buf,len,flag);if(ret0){if(errnoEAGAIN||errnoEINTR){return0;// 暂时无数据}ERR_LOG(SCOKET RECV FAILED!);// 拼写错误SCOKET - SOCKETreturn-1;}returnret;}ssize_tNonBlockRecv(void*buf,size_t len){returnRecv(buf,len,MSG_DONTWAIT);}recv返回实际接收字节数。ret 0对端关闭连接。ret 0EAGAIN/EWOULDBLOCK非阻塞下无数据。EINTR被信号中断。其他真正错误。MSG_DONTWAIT本次接收非阻塞不改变套接字整体属性。4.7Send()与NonBlockSend()ssize_tSend(constvoid*buf,size_t len,intflag0){ssize_t retsend(_sockfd,buf,len,flag);if(ret0){ERR_LOG(SOCKET SEND FAILED!);return-1;}returnret;}ssize_tNonBlockSend(void*buf,size_t len){returnSend(buf,len,MSG_DONTWAIT);}返回实际发送字节数。非阻塞下可能只发送部分数据需要应用层缓冲剩余数据。SIGPIPE信号需忽略否则向已关闭连接发送会崩溃。4.8Close()关闭套接字voidClose(){if(_sockfd!-1)close(_sockfd);_sockfd-1;}关闭 fd置为-1防止重复关闭。4.9CreaterServer()一键创建服务端boolCreaterServer(uint16_tport,conststd::stringip0.0.0.0,boolblock_flagfalse){if(Create()false)returnfalse;if(block_flag)NonBlock();// 注意block_flag 为 true 时反而设非阻塞命名相反if(Bind(ip,port)false)returnfalse;if(Listen()false)returnfalse;ReuseAddress();// 建议移到 Bind 之前returntrue;}默认ip 0.0.0.0监听所有网卡。block_flag命名有歧义实际true表示非阻塞。ReuseAddress()应在Bind()前调用。4.10CreateClient()一键创建客户端boolCreateClient(uint16_tport,conststd::stringip){if(Create()false)returnfalse;if(Connect(ip,port)false)returnfalse;returntrue;}4.11ReuseAddress()地址端口重用voidReuseAddress(){intval1;setsockopt(_sockfd,SOL_SOCKET,SO_REUSEADDR,(void*)val,sizeof(int));val1;setsockopt(_sockfd,SOL_SOCKET,SO_REUSEPORT,(void*)val,sizeof(int));}SO_REUSEADDR允许绑定处于TIME_WAIT的端口服务器可立即重启。SO_REUSEPORT允许多个套接字绑定相同 IP:端口实现负载均衡。val 1表示开启选项0表示关闭。SOL_SOCKET通用套接字层选项。4.12NonBlock()设置非阻塞voidNonBlock(){intflagfcntl(_sockfd,F_GETFL,0);fcntl(_sockfd,F_SETFL,flag|O_NONBLOCK);}获取当前文件状态标志加上O_NONBLOCK再设置回去。非阻塞是 Reactor 模型的基础防止accept/recv/send阻塞 EventLoop 线程。5. 关键知识点知识点说明字节序转换htons/htonl主机转网络ntohs/ntohl网络转主机地址转换inet_addr字符串转网络字节序推荐inet_pton错误处理errnoEAGAIN/EWOULDBLOCK表示非阻塞无数据EINTR表示被信号中断阻塞 vs 非阻塞非阻塞配合 epoll避免线程卡死地址重用SO_REUSEADDR解决 TIME_WAITSO_REUSEPORT支持多进程监听RAII析构自动关闭 fd避免资源泄漏SIGPIPE需忽略防止向已关闭连接发送数据导致进程退出6. 使用示例6.1 服务端#includeserver.hppintmain(){Socket lst_sock;lst_sock.CreaterServer(8500);// 默认阻塞while(1){intnewfdlst_sock.Accept();if(newfd0)continue;Socketcli_sock(newfd);charbuf[1024]{0};intretcli_sock.Recv(buf,1023);if(ret0){cli_sock.Close();continue;}cli_sock.Send(buf,ret);cli_sock.Close();}lst_sock.Close();return0;}6.2 客户端#includeserver.hppintmain(){Socket cli_sock;cli_sock.CreateClient(8500,127.0.0.1);std::string strhello;cli_sock.Send(str.c_str(),str.size());charbuf[1024]{0};cli_sock.Recv(buf,1023);DBG_LOG(%s,buf);return0;}7. 总结Socket类是对 Linux 原生 socket API 的轻量级封装核心接口创建Create绑定Bind监听Listen连接Connect接受Accept收发Recv/Send支持非阻塞版本关闭Close辅助ReuseAddress、NonBlock
企业数字化 ERP 产品动态
相关推荐
快降重英文长文本语义保真技术:英文学术论文降 AI 不篡改原意 英文论文降 AI,最怕的不是降不下去,而是降完之后原意被改坏了。导师看一眼说“这不是你原来写的意思”,审稿人批一句“the argument has shifted”,比 AI 率超标还麻烦。本文从技术角度拆解快降重的英文长文本语义保真机制&#x… · 2026/9/24 17:47:27
4个高权重位置,搞定小程序搜索排名优化 昨天有位做小程序的朋友私信问我:“小程序搜索排名还有什么好优化的?现在流量都被大平台吸走了,做这个纯属浪费时间。”我看到这条消息的时候愣了一下。做小程序搜索优化也快6年了,自己手上也管着十几个小程序,第一次有… · 2026/9/24 17:47:27
Python脉象识别系统从源码到实战:信号处理与特征分类全解析 简介:这是一套基于Python实现的中医脉象识别系统源码,面向医疗健康领域开发者、科研人员以及对智能诊断感兴趣的Python学习者。系统覆盖从脉象信号采集、去噪滤波、特征提取到模型训练与结果输出的完整流程,内置CNN、RNN等深度学习算法&#… · 2026/9/24 18:14:04
Java毕设考勤系统全流程实战:Spring Boot+小程序从表设计到部署避坑 简介:这是一套面向本科毕业设计的小程序上课考勤系统完整源代码,基于Spring Boot与微信小程序开发,适合Java学习者、毕设学生作为项目参考。系统实现了后台管理、小程序端GPS签到、定位打卡、迟到统计等核心考勤功能,设计获得优秀… · 2026/9/24 18:14:04
遗传算法与遗传编程预测股票价格:靠谱还是玄学? 简介:面向量化交易与机器学习初学者,这套算法交易实验代码以苹果股价预测为场景,分别采用遗传编程和遗传算法两种进化计算策略。遗传编程通过进化基于树的种群来最小化预测价格与实际价格之间的误差,并融合纳斯达克、苹果、标普等… · 2026/9/24 18:14:04
基于YOLOv8的大熊猫实时视觉检测与AR互动系统 简介:这是一套基于Python开发的大熊猫主题AI互动拍照系统源码,面向Web开发初学者与AI应用实践者,聚焦于计算机视觉与Web服务的融合落地。项目采用Flask或Django框架构建后端服务,集成姿态识别、风格迁移(CartoonGAN&am… · 2026/9/24 18:14:04
C#超市收银系统源码解析:事务扣库存与WinForm实战链路 简介:这是一套面向计算机专业本科生与毕业设计初学者的C#超市收银管理系统源码,聚焦零售场景下的收银流程优化与后台管理实践,助力开发者掌握企业级桌面应用开发全流程。资源共271个文件,包含106个核心业务逻辑.cs文件、27个运行依… · 2026/9/24 18:14:04
基于SpringBoot的宠物救助及领养平台的设计与实现-附源码 温馨提示:本人主页置顶文章(点我)开头有 CSDN 平台官方提供的学长联系方式的名片! 温馨提示:本人主页置顶文章(点我)开头有 CSDN 平台官方提供的学长联系方式的名片! 温馨提示:本人主页置顶文章(点我)开头有 CSDN 平台… · 2026/9/24 18:13:46
基于YOLOv8的渔船作业监控系统:从环境搭建到边缘部署全流程 简介:这是一套面向计算机、人工智能、自动化等专业学生与教师的毕业设计级项目资源,围绕YOLOv8实现渔船作业监控系统,可用于毕设、课程设计、大作业或项目立项演示。压缩包共97个文件,约24.21MB,以70个Python源码文件为… · 2026/9/24 0:00:13
1D-CNN时间序列建模实战:从Conv1d原理到工业落地 简介:面向时间序列数据建模的一维卷积神经网络完整实现,适合深度学习入门者及需要快速验证时序模型的研究者,能够从音频、文本、传感器或股价等序列中挖掘局部特征与时间依赖。压缩包体积很小,只有3KB,内含3个Python脚… · 2026/9/24 0:00:26
柔软的L:汉语语流中被忽视的舌肌张力控制 1. 这个“L”不是字母表里的L,而是舌尖上的L最近在几个方言群和语音教学社群里,反复看到有人发一句:“也说字母L:柔软的长舌”。初看以为是英语发音课笔记,点开才发现全是方言爱好者、播音系学生、语言康复师甚至戏曲演… · 2026/9/24 0:00:44