news 2026/8/25 14:40:12

C++ epoll 极简服务器代码

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
C++ epoll 极简服务器代码

epoll 是什么?

- Linux 下高性能 I/O 多路复用机制

- 用来同时监听很多个 socket/文件描述符,谁就绪就处理谁

- 是 Redis、Nginx、网关、高并发服务器 的核心

为什么要用 epoll?

对比:

- select/poll:每次都要遍历所有 fd,O(n),并发高就崩

- epoll:内核主动告诉你哪些就绪,O(1),百万并发无压力

三个核心 API

1. epoll_create
创建一个 epoll 实例,返回 epfd。

2. epoll_ctl
增/删/改要监听的 fd

- EPOLL_CTL_ADD

- EPOLL_CTL_MOD

- EPOLL_CTL_DEL

3. epoll_wait
阻塞等待事件就绪,返回就绪列表,不用遍历全部。

两种触发模式(超级重要)

1. 水平触发 LT(默认)

- 只要缓冲区有数据,就一直通知

- 简单、不容易丢数据

- 新手/通用场景用它

2. 边缘触发 ET

- 只有状态变化时才通知(无→有)

- 必须一次性读完所有数据

- 性能更高,Nginx/Redis 用它

工作流程(极简版)

1. 创建 socket → bind → listen

2. 创建 epoll 实例

3. 把 listenfd 加入 epoll

4. 循环 epoll_wait

5. 就绪:

- 是 listenfd → accept 新连接,加入 epoll

- 是普通 fd → read/write 处理数据

为什么 epoll 快?

- 内核事件驱动,不轮询

- mmap 共享内存,减少拷贝

- 内部用红黑树管理 fd,增删改极快

#include <stdio.h>

#include <stdlib.h>

#include <string.h>

#include <unistd.h>

#include <sys/socket.h>

#include <sys/epoll.h>

#include <netinet/in.h>

#include <fcntl.h>

#include <errno.h>

#define MAX_EVENTS 1024

#define PORT 8888

// 设置非阻塞

int set_nonblock(int fd) {

int flag = fcntl(fd, F_GETFL, 0);

fcntl(fd, F_SETFL, flag | O_NONBLOCK);

return 0;

}

int main() {

// 1. 创建监听 socket

int listen_fd = socket(AF_INET, SOCK_STREAM, 0);

struct sockaddr_in addr;

addr.sin_family = AF_INET;

addr.sin_addr.s_addr = INADDR_ANY;

addr.sin_port = htons(PORT);

// 端口复用

int opt = 1;

setsockopt(listen_fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));

bind(listen_fd, (struct sockaddr*)&addr, sizeof(addr));

listen(listen_fd, 128);

set_nonblock(listen_fd);

// 2. 创建 epoll

int epfd = epoll_create1(0);

struct epoll_event ev;

ev.events = EPOLLIN; // 监听读事件

ev.data.fd = listen_fd;

epoll_ctl(epfd, EPOLL_CTL_ADD, listen_fd, &ev);

struct epoll_event events[MAX_EVENTS];

printf("epoll server running on port %d...\n", PORT);

while (1) {

// 3. 等待事件

int nfds = epoll_wait(epfd, events, MAX_EVENTS, -1);

for (int i = 0; i < nfds; ++i) {

int fd = events[i].data.fd;

// 新连接

if (fd == listen_fd) {

int client_fd = accept(listen_fd, NULL, NULL);

set_nonblock(client_fd);

ev.events = EPOLLIN | EPOLLET; // ET 边缘触发

ev.data.fd = client_fd;

epoll_ctl(epfd, EPOLL_CTL_ADD, client_fd, &ev);

}

// 客户端发来数据

else {

char buf[1024];

ssize_t n = read(fd, buf, sizeof(buf));

if (n <= 0) {

close(fd);

epoll_ctl(epfd, EPOLL_CTL_DEL, fd, NULL);

} else {

write(fd, buf, n); // echo 回去

}

}

}

}

close(listen_fd);

close(epfd);

return 0;

}

g++ server.cpp -o epoll_server

./epoll_server

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/8/25 14:38:12

快解析:管家婆辉煌II TOP+异地高效协同办公实战指南

1. 为什么你的管家婆一到外地就“失联”&#xff1f;聊聊C/S架构的痛点 我猜很多用管家婆辉煌II TOP的朋友都遇到过这个头疼事儿&#xff1a;在公司里用得好好的&#xff0c;数据录入、查库存、打单子都挺顺&#xff0c;可一旦出差在外地&#xff0c;或者想在家加个班处理点急事…

作者头像 李华
网站建设 2026/7/14 16:53:53

GNSS数据处理实战:GAMP_GOOD配置文件(.cfg)深度解析与定制指南

1. 从“能用”到“好用”&#xff1a;为什么你需要定制GAMP_GOOD的.cfg文件&#xff1f; 很多刚接触GNSS数据处理的朋友&#xff0c;拿到GAMP_GOOD这个工具&#xff0c;第一反应就是照着教程跑通流程&#xff0c;把数据下载下来。这当然没错&#xff0c;能跑起来就是成功的第一…

作者头像 李华
网站建设 2026/8/25 14:37:07

VMware 克隆报错:虚拟磁盘修复实战与路径陷阱解析【避坑指南】

1. 克隆虚拟机时&#xff0c;那个让人头疼的“需要修复”弹窗 相信很多朋友在用VMware Workstation搭建测试环境、学习集群部署&#xff08;比如Hadoop、K8s&#xff09;或者批量复制虚拟机的时候&#xff0c;都干过“克隆”这个操作。这功能本来是为了省事&#xff0c;一键复制…

作者头像 李华
网站建设 2026/7/14 16:53:56

从Material到Adobe Color:10个设计师都在用的科研配色神器大盘点

从Material到Adobe Color&#xff1a;10个设计师与科研人都在用的配色神器深度解析 配色&#xff0c;这个看似感性的艺术&#xff0c;在设计与科研的交叉领域&#xff0c;却是一门严谨的科学。无论是为了在顶级期刊的图表中清晰传达数据趋势&#xff0c;还是在产品界面中引导用…

作者头像 李华
网站建设 2026/7/14 16:53:56

Git 中新建学习分支 + 暂存修改 + VSCode 可视化查看改动(超详细教程

目录 一、前言 二、创建一个独立学习分支 三、在学习分支中随意修改与注释 四、暂时保存修改 —— git stash 五、恢复暂存的修改 —— git stash pop 六、VSCode 左侧的可视化差异查看 1) 源代码管理 1.1&#xff09;未提交时&#xff0c;显示 No stashes could be fo…

作者头像 李华