前面我们已经知道WFNetworkTask是网络任务的统一壳CommRequest负责把它投递给通信框架那接下来真正的问题就是是谁在驱动连接建立、请求发送、响应接收、服务端回包和超时处理答案就是Communicator。它不是一个“普通的网络工具类”而是 Workflow 在通信层的总调度内核。一、先给 Communicator 一个定位Communicator的接口非常集中intrequest(CommSession*session,CommTarget*target);intreply(CommSession*session);intpush(constvoid*buf,size_t size,CommSession*session);intshutdown(CommSession*session);intbind(CommService*service);voidunbind(CommService*service);intsleep(SleepSession*session);intio_bind(IOService*service);从接口上就能看出它其实统一承接了三件事客户端通信服务端通信计时器与异步 IO 事件也就是说Communicator并不是“网络栈”那么简单它更像是 Workflow 的事件驱动运行时。二、Communicator 的底层资源组成它内部最重要的三个资源是struct__mpoller*mpoller;struct__msgqueue*msgqueue;struct__thrdpool*thrdpool;这三个东西刚好对应三层职责1.mpoller负责监听 fd 事件也就是 I/O 多路复用层。2.msgqueue负责在 poller 线程和 handler 线程之间传递结果。3.thrdpool负责运行 handler 线程池异步消费 poller 产出的结果。这说明 Communicator 的线程模型并不是“一个 epoll 线程干到底”而是典型的I/O 线程发现事件业务处理线程消费事件。这个架构非常适合高并发服务端场景。三、Communicator 管理的核心对象是什么1.CommTarget表示一个可通信目标里面保存了地址connect timeoutresponse timeoutSSL 配置idle connection 链表客户端请求最终就是发往某个CommTarget。2.CommSession表示一次通信会话。它持有targetconnoutinseqtimeout 状态可以把它理解成一次逻辑请求在通信内核里的执行现场。3.CommConnEntry这是Communicator.cc里最重要的内部结构之一structCommConnEntry{CommConnection*conn;longlongseq;intsockfd;intstate;interror;intref;SSL*ssl;CommSession*session;CommTarget*target;CommService*service;mpoller_t*mpoller;};它不是单纯的 socket 包装而是连接对象 会话对象 poller 状态 生命周期引用计数全部打包在一起。四、连接状态机是理解 Communicator 的关键CommConnEntry的状态定义非常值得背下来CONN_STATE_CONNECTING CONN_STATE_CONNECTED CONN_STATE_RECEIVING CONN_STATE_SUCCESS CONN_STATE_IDLE CONN_STATE_KEEPALIVE CONN_STATE_CLOSING CONN_STATE_ERROR这组状态基本概括了 Workflow 网络连接的一生正在连接已连接正在接收本次收发成功空闲可复用服务端 keep-alive 等待下一次请求正在关闭发生错误这里有个很重要的点Workflow 不是“每次请求必新建连接”而是内建了连接复用和连接状态迁移。这也是它性能表现好的重要原因之一。五、发送流程从 session 到 socket一个客户端请求真正进入Communicator后核心链路大概是CommRequest::dispatch()CommScheduler::request()Communicator::request()建连或复用连接message_out()编码send_message()send_message()又会拆成两步1. 尝试同步发送cntthis-send_message_sync(vectors,cnt,entry);if(cnt0)returncnt;也就是说如果 socket 当前可写Workflow 会尽量一次性直接写出去减少额外 epoll 轮转。2. 剩余部分再异步发送returnthis-send_message_async(end-cnt,cnt,entry);这是一种非常实用的优化策略能同步发完就不要拖到异步发不完再把后半段挂给 poller相比那种“一律交给 epoll 写”的实现这样的路径更短。六、收包流程消息不是按 socket而是按协议对象推进的真正的亮点在这里。Workflow 收到数据后并不是简单把 buffer 扔给用户而是直接让协议对象接管。核心逻辑在append_message()retin-append(buf,size);if(ret0){entry-stateCONN_STATE_SUCCESS;...}这里的in其实就是具体协议对象例如HttpResponseMySQLResponseRedisResponse也就是说Communicator 负责收字节流协议对象负责决定“消息是否完整”。这是一个很好的分层传输层不关心 HTTP Header 是什么协议层不关心 epoll 怎么触发七、为什么 create_request / create_reply 这两个函数很重要这两个函数几乎就是 Communicator 与协议层的桥。create_reply()用于客户端场景请求发出去后构造一个响应对象来收包。create_request()用于服务端场景收到连接后构造一个请求对象来解析客户端发来的消息。这两个函数说明 Workflow 在通信层的抽象非常统一客户端发送request接收reply服务端接收request发送reply在底层看来二者只是“创建哪个协议对象来消费字节流”的差异。八、服务端为什么也能长得这么统一服务端接收连接的入口在handle_listen_result()。它做的事大概是accept 新连接构造CommConnEntry如果是 SSL先走握手否则直接挂入 READ 事件后面当请求解析成功后会走到handle_incoming_request()并最终把状态回传成CS_STATE_TOREPLY这个状态的意思很直白请求已经完整到达现在轮到上层业务决定要不要回包。所以服务端的本质也是通信内核负责把 request 收完整上层任务流负责业务处理通信内核再负责把 reply 发回去整个模式非常对称。九、超时为什么放在 Communicator 里而不是协议层里很多框架会把超时分散在上层。Workflow 把大量超时控制集中在Communicator这是更合理的做法。原因很简单超时本质上是 I/O 事件调度的一部分。比如connect timeoutsend timeoutreceive timeoutkeep-alive timeout这些时间点都和 fd 的生命周期强相关放在通信内核里统一管理最不容易出错。同时由于CommSession里维护了begin_time和timeoutCommunicator 还可以做分阶段剩余时间计算而不是每一段都重新开始计时。这就是first_timeout()/next_timeout()这组函数的价值。十、为什么要把 poller 结果再扔进 handler 线程池这是很多人读 Communicator 时最容易问的问题“poller 线程里直接处理不行吗”可以但 Workflow 没这么做。它的做法是poller 线程负责发现事件事件结果塞进msgqueuehandler 线程池消费结果执行handle_poller_result()这样设计的好处是1. poller 线程更纯粹它专注做 I/O 复用不被复杂业务逻辑拖慢。2. 协议解析和状态机推进可以并行化多个 handler 线程可以同时处理不同连接的结果。3. 更适合大规模并发I/O 线程保持敏捷CPU 密集部分交给 handler 线程池吸收。这实际上是一个非常经典、非常实用的 reactor 变体。十一、Communicator 其实已经接近“微内核”当你把Communicator提供的能力列出来时会发现它已经很像一个微型异步运行时TCP clientTCP serverSSL 握手连接复用timereventfd/pipe 驱动file IO 事件接入poller/handler 线程协作而且这些能力不是松散拼接的而是统一通过CommSessionCommTargetpoller_datapoller_result这些结构组织起来的。这也是 Workflow 为什么能支撑 HTTP、Redis、MySQL、DNS 等多协议共存的根本原因。十二、读 Communicator 时最该抓住什么我建议你不要一上来就陷进每一个分支而是先抓住这条主线客户端路径请求进来获取 target建连/复用连接编码发送构造 response 对象收包解析成功后回调上层 session服务端路径listen fd 收到连接accept构造 request 对象收包解析成功后上抛TOREPLY用户逻辑处理reply / shutdown / keep-alive只要这两条线在脑子里顺了Communicator剩下的大多数细节就都是围绕它们展开的工程实现。十三、小结Communicator是 Workflow 通信层最核心的模块。它做的事不只是“封装 socket”而是驱动连接状态机管理请求/响应生命周期连接协议对象与 I/O 事件协调 poller 线程和 handler 线程给上层任务一个统一、稳定的通信抽象可以用一句话总结WFNetworkTask是网络任务的接口层Communicator是网络任务的执行内核。