核心内容摘要
岁月鎏金,情意绵长:一位中国老太太的“性70”人生叙事
用 muduo 写一个 TCP 服务器基于epoll 线程池接收客户端连接客户端发什么服务器原样返回Echo打印连接、断开、收发数据日志muduo 的核心思想网络 I/O 与业务逻辑彻底解耦muduo 的核心模型muduo Reactor One Loop Per Thread整体结构分析main()└── EventLoop loop // 主 Reactorepoll└── ChatServer server└── TcpServer _server├── ConnectionCallback├── MessageCallback└── 线程池 (setThreadNum)典型 muduo Reactor 模型主线程(EventLoop)||--- 接收新连接|--- 分发连接到子线程(EventLoop)||--- 处理读写事件整体代码/* muduo网络库给用户提供两个主要的类 TcpServer:用户编写服务器程序的 TcpClient:用户编写客户端程序的 epoll 线程池 好处能够把网络I/O的代码和业务代码区分开来 用户的连接与断开 用户的可读写事件 */ #includemuduo/net/TcpServer.h #includemuduo/net/EventLoop.h #includeiostream #includefunctional using namespace std; using namespace muduo; using namespace muduo::net; using namespace placeholders; /*基于muduo网络库开发服务器程序
组合TcpSever对象
创建EventLoop事件循环对象的指针
明确TcpServer构造函数需要什么参数输出ChatServer的构造函数 */ class ChatServer { public: ChatServer(EventLoop * loop,const InetAddress listenAddr,const string nameArg):_server(loop,listenAddr,nameArg),_loop(loop) { _server.setConnectionCallback(bind(ChatServer::onConnection,this,_
); _server.setMessageCallback(bind(ChatServer::onMessage,this,_1,_2,_
); //设置EventLoop的线程个数 _server.setThreadNum(
; } //启动ChatServer服务 void start() { _server.start(); } private: //TcpServer绑定的回调函数当有新连接或连接中断时调用 void onConnection(const TcpConnectionPtr conn) { if(conn-connected()) { coutconn-peerAddress().toIpPort() - conn-localAddress().toIpPort()state:onlineendl; } else{ coutconn-peerAddress().toIpPort() - conn-localAddress().toIpPort()state:offlineendl; conn-shutdown();//close(fd) _loop-quit(); } } //TcpServer绑定的回调函数当有新数据时调用 void onMessage(const TcpConnectionPtr conn, Buffer* buffer, Timestamp time) { string bufbuffer-retrieveAllAsString(); coutrecv data:buftime:time.toString()endl; conn-send(buf); } TcpServer _server; EventLoop* _loop; }; int main() { EventLoop loop;//epoll InetAddress addr(
127.
0.
1,
; ChatServer server(loop,addr,ChatServer); server.start();//listen epoll_ctlepoll loop.loop();//epoll_wait以阻塞方式等待新用户连接已连接用户的读写事件等 return 0; }头文件 命名空间#include muduo/net/TcpServer.h #include muduo/net/EventLoop.h #include functional using namespace muduo; using namespace muduo::net; using namespace placeholders;EventLoopReactor 的本体EventLoop loop;EventLoop 是什么EventLoop epoll 事件分发器loop.loop() 在干什么void EventLoop::loop() { while (!quit_) { activeChannels_ poller_-poll(); // epoll_wait for (Channel* ch : activeChannels_) { ch-handleEvent(); } } }为什么 EventLoop 不能拷贝内部持有 fd绑定线程 ID一个 loop 只能在一个线程里跑TcpServerTcpServer 本质是什么TcpServer Acceptor 线程池 连接管理器class TcpServer { EventLoop* loop_; // 主 loop Acceptor acceptor_; // 监听 socket EventLoopThreadPool threadPool_; mapstring, TcpConnectionPtr connections_; };TcpServer 的职责功能谁干accept 新连接Acceptor分配 IO 线程ThreadPool管理连接connections_注册回调setXXXCallbackInetAddress地址封装InetAddress addr(
127.
0.
1,
;等价于sockaddr_in addr; addr.sin_family AF_INET; addr.sin_port htons(
; addr.sin_addr.s_addr inet_addr(
127.
0.
0.