cpp
// 5. 将监听套接字添加到epoll监控
struct epoll_event event{};
event.events = EPOLLIN; // 监控可读事件
event.data.fd = listen_sockfd;
if (epoll_ctl(epoll_fd, EPOLL_CTL_ADD, listen_sockfd, &event) < 0) {
perror("epoll_ctl add listen failed");
return 1;
}
把监听套接字加入 epoll 监控
这是 epoll 高并发服务器最核心的操作之一 :向 epoll 监控器注册要监听的 socket 和事件。
整段代码的核心作用(大白话)
c
// 告诉 epoll 监控中心:
// 帮我盯着【监听套接字】,一旦有客户端来连接(可读事件),立刻通知我!
这一步 = 给服务器装上"雷达",开始扫描客户端连接请求。
逐行深度拆解
1. 创建 epoll 事件结构体
c
struct epoll_event event{};
这是什么?
epoll_event:epoll 事件描述体- 作用:告诉 epoll 要监听哪个 socket、监听什么事件、事件触发后带什么数据回来
结构体内部长这样(必须看懂):
c
struct epoll_event {
uint32_t events; // 要监听的事件类型(如:可读、可写、异常)
epoll_data_t data; // 事件触发时,带回的数据(通常存 socket 文件描述符)
};
2. 设置要监听的事件类型
c
event.events = EPOLLIN; // 监控可读事件
① EPOLLIN 是什么?
全称:Event POLL IN ------ 监听「可读事件」
- 含义:只要对应的 socket 有数据可读,就触发通知
- 对监听套接字 来说:
EPOLLIN 事件触发 = 有客户端来连接了!
为什么监听套接字只需要 EPOLLIN?
- 监听套接字不收发数据 ,只负责接收新连接
- 客户端发起连接 → 内核把连接放入队列 → 监听套接字变为「可读」
- epoll 检测到 EPOLLIN → 通知程序去调用
accept()接收连接
其他常见事件(了解即可):
EPOLLOUT:可写事件(发送数据时用)EPOLLET:边缘触发(高性能模式)EPOLLERR:异常事件
3. 设置事件触发后带回的数据
c
event.data.fd = listen_sockfd;
作用:
把监听套接字的文件描述符存进事件结构体
- 当 epoll 检测到事件触发时,会把这个 fd 原样返回
- 程序拿到 fd 就知道:哦!是监听套接字有动静了,该去 accept 了!
为什么要存 fd?
epoll 会监控成百上千个 socket
必须带上标识,才能知道到底是哪个 socket 触发了事件。
4. 核心函数:epoll_ctl(操控 epoll 监控列表)
c
epoll_ctl(epoll_fd, EPOLL_CTL_ADD, listen_sockfd, &event)
① 函数作用
对 epoll 监控列表进行增、删、改操作
- 增:添加要监控的 socket
- 删:取消监控
- 改:修改监控的事件类型
② 四个参数逐行解释(重中之重)
| 参数 | 含义 | 解释 |
|---|---|---|
| epoll_fd | epoll 实例的文件描述符 | 你之前 epoll_create1 创建的监控器 |
| EPOLL_CTL_ADD | 操作类型:添加 | 把 socket 加入 epoll 监控列表 |
| listen_sockfd | 要监控的目标 socket | 监听套接字(负责接收客户端连接) |
| &event | 事件配置信息 | 告诉 epoll:监听 EPOLLIN 事件,触发后返回 listen_sockfd |
③ 三种操作类型(必记)
EPOLL_CTL_ADD:添加 新的 socket 到 epollEPOLL_CTL_DEL:删除 不再监控的 socketEPOLL_CTL_MOD:修改 已添加 socket 的监听事件
5. 返回值判断
c
if (...) < 0) {
perror("epoll_ctl add listen failed");
return 1;
}
- 成功:返回
0 - 失败:返回
-1 - 常见失败原因:
- epoll_fd 非法
- listen_sockfd 未绑定/未监听
- 重复添加同一个 socket
完整原理(通俗到离谱)
把 epoll 当作 小区保安室:
struct epoll_event event= 一张监控登记表event.events = EPOLLIN= 登记要监控:有人来访event.data.fd = listen_sockfd= 监控目标:小区大门epoll_ctl(..., EPOLL_CTL_ADD, ...)= 把登记表交给保安- 保安(epoll)开始盯着大门,有人来就立刻通知你
这行代码执行完后发生了什么?
- 内核把
listen_sockfd加入 epoll 监控红黑树 - epoll 开始自动监控该套接字的 EPOLLIN 事件
- 一旦有客户端连接 → 内核立刻通知 epoll
- 程序调用
epoll_wait就能拿到事件,去处理连接
极简总结(超好记)
- struct epoll_event:epoll 事件登记表
- EPOLLIN:监听「有客户端连接」事件
- event.data.fd:告诉 epoll,触发后带回监听套接字
- epoll_ctl(ADD) :把监听套接字注册到 epoll 监控
- 核心意义 :让 epoll 帮你盯着端口,有连接就通知,不用死等
一句话总结
这行代码 = 给 epoll 装上"连接雷达",让服务器能高效感知所有客户端的连接请求!
下一步就是最关键的 epoll_wait() ------ 等待客户端连接 / 数据到来