day16-Acceptor
Acceptor是muduo 网络库核心的TCP 连接接收器类,专门负责监听端口、接收新的客户端 TCP 连接
Acceptor.h
1 |
|
class Acceptor : noncopyable:Acceptor 持有唯一的监听 Socket、Channel 资源,复制会导致资源冲突、文件描述符错乱。
核心回调类型
1 | using NewConnectionCallback = std::function<void(int sockfd, const InetAddress&)>; |
当 Acceptor 接收新连接后,调用这个回调,把新连接的 fd和客户端地址传给上层(TcpServer)处理。
私有成员变量
1 | private: |
用成员对象(实例)不用指针:生命周期严格绑定,Acceptor 销毁 → socket/channel 自动销毁
私有核心方法
1 | private: |
处理新连接到达的读事件
公有接口
1 | Acceptor(EventLoop *loop, const InetAddress &listenAddr, bool reuseport); |
传入:事件循环、监听地址、端口复用开关
核心工作:创建监听 socket → 绑定 IP + 端口 → 初始化 Channel
1 | void setNewConnectionCallback(const NewConnectionCallback &cb) |
上层(TcpServer)注册回调,接收新连接通知
1 | bool listenning() const { return listenning_; } // 获取监听状态 |
Acceptor.cc
1 | static int createNonblocking() |
- 参数详解:
SOCK_STREAM:TCP 流式套接字SOCK_NONBLOCK:创建 socket 时直接设置非阻塞,比后面用 fcntl 改更高效SOCK_CLOEXEC:调用 exec 执行新程序时,自动关闭这个 socket,防止父进程创建的 socket 被子进程意外继承,导致文件描述符泄露、端口无法释放
- 在** .cc/.cpp 文件里,函数前加
static:这个函数只在当前文件可见**,其他文件看不到、调用不到。
1 | Acceptor::Acceptor(EventLoop* loop, const InetAddress& listenAddr, bool reuseport) |
- 给 channel 绑定读事件回调 → 有新连接时调用 handleRead
- 调用刚才的工具函数,创建非阻塞 TCP socket,得到监听 fd(listenfd),封装成
Socket对象,由 Acceptor 持有管理 - 为什么用 std::bind?
- handleRead 是成员函数
- 调用成员函数必须有 this
- std::bind 把:
&Acceptor::handleRead + this绑定成一个可以直接调用的回调函数
- 构造函数不直接启动监听(listen),由上层 TcpServer 控制何时启动监听
- 析构函数,先取消所有监听事件,再从
EventLoop中移除这个Channel
调用逻辑
1 | 客户端发起连接 |
1 | void Acceptor::listen() |
先调用系统的listen函数开始监听,再通过enableReading调用到epoll_ctl开始监听读事件
1 | void Acceptor::handleRead() |
- 核心功能:
- 调用 accept 接收新连接,得到客户端通信 fd(connfd)
- 获取客户端 IP + 端口(peerAddress存储)
- 通过回调交给 TcpServer,或者没人要就直接关闭
- 调用时机:
- 客户端完成三次握手,listenfd 变成可读
- 由 Channel 的读事件回调触发执行
EMFILE:当前进程打开的文件描述符达到上限,达到上限后 accept 会失败,无法建立新连接- Acceptor 只做 接收连接,连接建立后的 IO 通信 交给 TcpConnection + subLoop
- 没有回调就要直接 close (connfd),newConnectionCallback_ 是空 → 没人接管这个连接,此时还没进入业务通信阶段,没有数据需要收发,直接关闭最安全
源码地址
Acceptor.h:https://gitee.com/lpzdinghai/lpzmuduo/blob/master/Acceptor.h
Acceptor.cc:https://gitee.com/lpzdinghai/lpzmuduo/blob/master/Acceptor.cc
All articles on this blog are licensed under CC BY-NC-SA 4.0 unless otherwise stated.