Back to VNotes

C++ WebServer / 03

v2.0:引入 epoll 多路复用

v2.0 把单连接等待改成事件驱动等待。主线程通过 epoll_wait 同时管理多个 fd,只有连接就绪时才处理。

这一阶段要解决什么问题

阻塞式服务器无法同时处理多个客户端。引入 epoll 后,主线程可以把 listen_fd 和 conn_fd 都交给内核监听,通过就绪事件决定下一步处理哪个连接。

原来的实现有什么缺陷

原来的 accept/read 是面向单连接的等待模型。连接数量一多,服务器不知道哪个 fd 已经准备好,只能被当前阻塞点牵着走。

我是怎么改的

用 epoll_create1 创建 epoll 实例,用 epoll_ctl 把 listen_fd 加入监听集合。accept 新连接后,再把 conn_fd 加入 epoll。事件循环只围绕 epoll_wait 展开。

核心代码 / 关键逻辑

epoll_fd = epoll_create1(EPOLL_CLOEXEC);
epoll_ctl(epoll_fd, EPOLL_CTL_ADD, listen_fd, &listen_event);

while (running) {
    int n = epoll_wait(epoll_fd, events.data(), MAX_EVENT_NUM, 1000);
    for (int i = 0; i < n; ++i) {
        if (events[i].data.fd == listen_fd) handle_new_connection();
        else handle_read_or_write(events[i]);
    }
}

踩坑记录

epoll 的价值不是让 read/write 本身变快,而是让一个线程管理大量连接的就绪事件。如果这个概念没想清楚,很容易把 epoll 写成“更复杂的阻塞服务器”。