恒美微站 Logo 恒美微站
  • 首页
  • 关于我们
  • 建站服务
  • 主题模板
  • 案例展示
  • 资讯中心
  • 联系我们

网络编程(5)—— Reactor实现(v1)

  • 首页
  • 资讯中心
  • /
  • 网络编程(5)—— Reactor实现(v1)

相关资讯

还在手动重复点击?这款免费开源鼠标连点器帮你把双手还给自己 2026/8/18 13:13:57
ScheduledThreadPoolExecutor 2026/8/18 13:13:57
3步解决老游戏黑屏:d3d8to9让D3D8游戏无缝运行在D3D9上 2026/8/18 13:13:57

最新资讯

轻松搞定Windows安卓应用安装:APK Installer 一劳永逸使用指南
Honey Select 2汉化去码一次搞定:HF Patch新手安装实操指南
Python邮件自动化:从SMTP协议到实战,掌握smtplib与email库
电磁能量技术解析:从感应加热到无线传能的工程实践
《技术大败局》从分水岭到2.1:一份关于“在事实与叙事之间建立标准”的思维笔记
Switch-Toolbox 实测手记:免费开源、零代码,任天堂 Switch/3DS/Wii U 游戏文件一次搞定

今日推荐

数据缺失处理:从MCAR、MAR到MNAR的机制解析与多重插补实践
MAGS-SLAM:多智能体协同3D高斯泼溅SLAM系统解析
LLM智能体记忆管理:基于关键词门控的混合激活机制CAMeR详解

本周热门

【文章复现】非线性值迭代自适应动态规划(ADP):离散时间非线性系统的策略迭代自适应动态规划算法研究附Matlab代码
【双层规划,节点出清价,绿证交易,CVaR方法】两级电力市场环境下计及风险的省间交易商最优购电模型附Matlab代码
隐式mpc+自适应mpc+时变mpc,线性时变模型预测控制附Simulink仿真

本月精选

如何用DamaiHelper实现演唱会门票的智能自动化抢购:完整技术解决方案指南
第4篇:59 倍性能差距的索引瓶颈定位——一次教科书级的全表扫描调优
终极歌词批量下载神器:5分钟解决离线音乐库歌词同步难题

网络编程(5)—— Reactor实现(v1)

发布时间:2026/8/18 13:13:57
网络编程(5)—— Reactor实现(v1) 文章目录回顾Reactor_v1实现Socket类实现头文件源文件InetAddr类的实现头文件源文件Acceptor类的实现头文件源文件SocketIO类的实现头文件源文件TcpConnection类的实现头文件源文件回顾先回顾一下我们整个的实现框架所以第一步应该是实现的是——封装系统调用另外为了方便打印调试信息可以把日志系统用单例模式先实现出来。关于用单例模式实现日志系统我们在之前的文章中已经实现过了这里就不过多赘述了。详情可以跳转到该文章中查看Reactor网络模型本质上就是使用epoll的并发网络模型通过连接器连接到服务器网络然后注册三个事件(对应epoll的三个接口函数)通过事件驱动(事件循环和事件分发)来响应客户端的请求。Reactor_v1实现在写代码之前要整理一下思绪框架图中已经很明确的写出了有哪些类我们在第一个版本的内容中实际上就是对系统调用的封装下面就画一个类图整理一下具体实现的内容。Acceptor类中可以将地址复用、端口复用、bind、listen这些写法固定的流程封装在一个ready函数中。关于其它类行该可以比较容易的理清思路。需要着重考虑的是IO操作因为使用send/recv或write/read一次处理的字符数量是由上限的。所以我们应该设置一个合适大小的缓冲用来接收数据流。Socket类实现头文件/** * 封装文件描述符 */#ifndef_SOCKET_H#define_SOCKET_H#includesys/types.h#includesys/socket.hclassSocket{public:Socket();/** * param fd * 禁止隐式转换防止出现问题 */explicitSocket(intfd);~Socket();intgetFd();private:int_fd;};#endif//_SOCKET_H源文件/** * 封装文件描述符 */#includeSocket.h#includestdio.h#includestdlib.h/** * Socket implementation */Socket::Socket(){_fd::socket(AF_INET,SOCK_STREAM,0);if(_fd-1){perror(socket error);exit(EXIT_FAILURE);}}/** * param fd */Socket::Socket(intfd):_fd(fd){}Socket::~Socket(){}/** * return int */intSocket::getFd(){return_fd;}InetAddr类的实现头文件/** * 地址相关操作 */#ifndef_INETADDRESS_H#define_INETADDRESS_H#includestring#includenetinet/in.h#includenetinet/ip.h#includesys/socket.h#includearpa/inet.husingstd::string;classInetAddress{public:/** * param ip * param port */InetAddress(conststringip,unsignedshortport);/** * param addr */InetAddress(conststructsockaddr_inaddr);~InetAddress();stringgetIp();unsignedshortgetPort();conststructsockaddr_in*getInetAddressPtr();private:structsockaddr_in_addr;};#endif//_INETADDRESS_H源文件/** * 地址相关操作 */#includeInetAddress.h/** * InetAddress implementation *//** * param ip * param port */InetAddress::InetAddress(conststringip,unsignedshortport){_addr.sin_familyAF_INET;_addr.sin_porthtons(port);_addr.sin_addr.s_addr::inet_addr(ip.c_str());}/** * param addr */InetAddress::InetAddress(conststructsockaddr_inaddr):_addr(addr){}InetAddress::~InetAddress(){}/** * return string */stringInetAddress::getIp(){string temp::inet_ntoa(_addr.sin_addr);returntemp;}/** * return unsigned short */unsignedshortInetAddress::getPort(){return::ntohs(_addr.sin_port);}/** * return const struct sockaddr_in * */conststructsockaddr_in*InetAddress::getInetAddressPtr(){return_addr;}Acceptor类的实现头文件/** * 连接器的实现 */#ifndef_ACCEPTOR_H#define_ACCEPTOR_H#includeInetAddress.h#includeSocket.husingstd::string;classAcceptor{public:/** * param ip * param port */Acceptor(conststringip,unsignedshortport);~Acceptor();voidready();intaccept();private:Socket _sock;InetAddress _addr;voidsetReuseAddr();voidsetReusePort();voidbind();voidlisten();};#endif//_ACCEPTOR_H源文件/** * 连接器的实现 */#includeAcceptor.h/** * Acceptor implementation *//** * param ip * param port */Acceptor::Acceptor(conststringip,unsignedshortport):_sock(),_addr(ip,port){}Acceptor::~Acceptor(){}/** * return void */voidAcceptor::ready(){setReuseAddr();setReusePort();bind();listen();return;}/** * return int */intAcceptor::accept(){intclientfd::accept(_sock.getFd(),NULL,NULL);if(clientfd-1){perror(accept error);return-1;}returnclientfd;}/** * return void */voidAcceptor::setReuseAddr(){intopt1;if(::setsockopt(_sock.getFd(),SOL_SOCKET,SO_REUSEADDR,opt,sizeof(opt))-1){perror(reuse sockaddr error);exit(EXIT_FAILURE);}return;}/** * return void */voidAcceptor::setReusePort(){intopt1;if(::setsockopt(_sock.getFd(),SOL_SOCKET,SO_REUSEPORT,opt,sizeof(opt))-1){perror(reuse port error);exit(EXIT_FAILURE);}return;}/** * return void */voidAcceptor::bind(){if(::bind(_sock.getFd(),(structsockaddr*)_addr.getInetAddressPtr(),sizeof(structsockaddr))-1){perror(bind error);exit(EXIT_FAILURE);}return;}/** * return void */voidAcceptor::listen(){if(::listen(_sock.getFd(),100)-1){perror(listen error);exit(EXIT_FAILURE);}return;}SocketIO类的实现头文件/** * IO操作 */#ifndef_SOCKETIO_H#define_SOCKETIO_H#includeunistd.h#includeerrno.h#includestdlib.h#includestdio.h#includesys/socket.h#includesys/types.hclassSocketIO{public:/** * param fd */explicitSocketIO(intfd);~SocketIO();/** * param buf * param len */intreadn(char*buf,intlen);/** * param buf * param len */intreadLine(char*buf,intlen);/** * param buf * param len */intwriten(constchar*buf,intlen);private:int_fd;};#endif//_SOCKETIO_H源文件/** * IO操作 */#includeSocketIO.h/** * SocketIO implementation *//** * param fd */SocketIO::SocketIO(intfd):_fd(fd){}SocketIO::~SocketIO(){if(_fd!-1){close(_fd);_fd-1;}}/** * param buf * param len * return int */intSocketIO::readn(char*buf,intlen){intremainlen;// 剩余没读的字节intret0;char*pstrbuf;while(remain0){ret::read(_fd,pstr,sizeof(remain));if(ret-1errnoEINTR){::perror(read error);return-1;}elseif(ret0){break;}else{pstrret;remain-ret;}}returnlen-remain;}/** * param buf * param len * return int */intSocketIO::readLine(char*buf,intlen){intremainlen-1;intret0,total0;char*pstrbuf;while(remain0){ret::recv(_fd,pstr,remain,MSG_PEEK);if(ret-1errnoEINTR){::perror(readLine error);return-1;}elseif(ret0){break;}else{for(inti0;iret;i){if(pstr[i]\n){intszi1;readn(pstr,sz);pstrsz;*pstr\0;returnsztotal;}}readn(pstr,ret);totalret;pstrret;remain-ret;}}*pstr\0;returntotal;}/** * param buf * param len * return int */intSocketIO::writen(constchar*buf,intlen){intremainlen;constchar*pstrbuf;intret0;while(remain0){retwrite(_fd,pstr,remain);if(ret-1errnoEINTR){::perror(writen error);return-1;}elseif(ret0){break;}else{pstrret;remain-ret;}}returnlen-remain;}TcpConnection类的实现头文件/** * 连接管理 */#ifndef_TCPCONNECTION_H#define_TCPCONNECTION_H#includestring#includeSocketIO.husingstd::string;classTcpConnection{public:/** * param fd */explicitTcpConnection(intfd);~TcpConnection();stringreceive();/** * param msg */voidsend(conststringmsg);private:SocketIO _sockIO;};#endif//_TCPCONNECTION_H源文件/** * 连接管理 */#includeTcpConnection.h/** * TcpConnection implementation *//** * param fd */TcpConnection::TcpConnection(intfd):_sockIO(fd){}TcpConnection::~TcpConnection(){}/** * return string */stringTcpConnection::receive(){charbuffer[1024]{0};_sockIO.readLine(buffer,sizeof(buffer));returnstring(buffer);}/** * param msg * return void */voidTcpConnection::send(conststringmsg){_sockIO.writen(msg.c_str(),msg.size());return;}以上就是Reactor的全部函数完成了对系统调用的封装。下面再写一个测试文件#includeAcceptor.h#includeTcpConnection.h#includeiostreamusingstd::cout;usingstd::endl;voidtest0(){Acceptoracceptor(0.0.0.0,8080);acceptor.ready();TcpConnectioncon(acceptor.accept());while(1){/* cout recv msg from client: con.receive() endl; *//* con.send(hello,world\n); */string msgcon.receive();coutrecv msg from client: msgendl;con.send(msg:msg);}}intmain(){test0();return0;}下面再开一个终端自测一下基本上还是符合我们预期的也就是说明我们对于底层的封装没有了太大问题。我们的Reactor第一代基本完成了当然可以把之前封装的log4cpp的代码替代perror()。下面的工作就是完成核心层事件驱动的代码就是对epoll的封装另外TcpConnection是用来管理连接的所以当我们使用服务器采用事件驱动的形式时TcpConnection中的数据成员和成员函数也要随之变动。

关于恒美微站

恒美微站专注于为个体商户、工作室提供极简自助建站服务,让每个人都能轻松拥有专业网站。

快速链接

  • 关于我们
  • 建站服务
  • 主题模板
  • 案例展示
  • 资讯中心

服务项目

  • 可视化建站
  • 拖拽编辑
  • 主题定制
  • SEO 优化
  • 网站托管

联系方式

  • 📍 地址:北京市朝阳区建国路 88 号
  • 📞 电话:400-888-8888
  • ✉️ 邮箱:info@hmyw.cn
  • 🕐 时间:周一至周日 9:00-18:00

© 2024 恒美微站 hmyw.cn 版权所有 | 京 ICP 备 12345678 号