本文从 TcpServer accept 新连接开始,追踪 Socket、Session 的创建、数据读取、生命周期管理的完整流程,深入到 epoll 事件注册、recv 系统调用级别。
1. 核心类关系
TcpServer Session 工厂 + 监听 Socket 持有者 │ ├─ Socket fd 封装,管理读写回调 │ ├─ _sock_fd 原始 fd │ ├─ _poller 所属 EventPoller │ ├─ _on_read_cb 数据到达回调 │ └─ _on_err_cb 错误回调 │ └─ Session (TcpSession) 业务会话 ├─ _sock Socket::Ptr(共享所有权) ├─ onRecv() 纯虚函数,子类实现 └─ onError() 错误处理继承体系:
classSession:publicstd::enable_shared_from_this<Session>{// 基础会话,携带 Socket};classTcpSession:publicSession{// TCP 会话基类virtualvoidonRecv(constBuffer::Ptr&buf)=0;};classRtspSession:publicTcpSession,publicRtspSplitter,...{// RTSP 协议会话};2. TcpServer 启动与监听
2.1 start 模板函数
// ZLToolKit/src/TcpServer.htemplate<typenameSessionType>voidTcpServer::start(uint16_tport,...){// 保存 Session 工厂_session_creator=[](constSocket::Ptr&sock,constSockAddress&addr)->Session::Ptr{returnstd::make_shared<SessionType>(sock,addr);};// 开始监听start_l(port);}2.2 start_l — 绑定与监听
voidTcpServer::start_l(uint16_tport){_socket=Socket::createSocket(_poller,true);// 1. socket() → 返回 fd// 2. setsockopt(SO_REUSEADDR)// 3. bind("0.0.0.0", port)// 4. listen(SOMAXCONN)_socket->bind(port);// 5. 注册 accept 回调_socket->setOnAccept([this](constSocket::Ptr&sock,constSockAddress&addr){onAcceptConnection(sock,addr);});// 6. 将 listen_fd 注册到 epoll// epoll_ctl(_epoll_fd, EPOLL_CTL_ADD, listen_fd, EPOLLIN)}网络库级调用链:
Socket::bind() → ::socket(AF_INET, SOCK_STREAM, 0) → ::setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, ...) → ::bind(fd, (struct sockaddr*)&addr, sizeof(addr)) → ::listen(fd, SOMAXCONN) → Socket::setOnAccept() → EventPoller::addEvent(fd, EPOLLIN, accept_cb) → epoll_ctl(_epoll_fd, EPOLL_CTL_ADD, fd, &ev)3. 新连接 Accept 流程
当 epoll_wait 检测到 listen_fd 可读时:
3.1 Socket::onAccept
voidSocket::onAccept(){while(true){// 系统调用:accept4(非阻塞)