网站开发好后要做什么,事业单位网站设计,wordpress不能注册,详情页设计怎么收费epoll并发编程 epoll并发编程背景知识epoll 的特点epoll 的工作原理epoll 和 select/poll 的区别 epoll并发服务器思路重点代码分析git地址参考书目 epoll并发编程背景知识
epoll 是 Linux 中用于处理大量文件描述符的 I/O 事件通知机制。在传统的 I/O 模型中#xff0c;一般… epoll并发编程 epoll并发编程背景知识epoll 的特点epoll 的工作原理epoll 和 select/poll 的区别 epoll并发服务器思路重点代码分析git地址参考书目 epoll并发编程背景知识
epoll 是 Linux 中用于处理大量文件描述符的 I/O 事件通知机制。在传统的 I/O 模型中一般使用 select 或 poll 来进行多路复用但随着连接数的增加它们的性能开始下降。而 epoll 的设计旨在解决这个问题提高大规模并发的网络应用性能。
epoll 的特点
高性能 epoll 可以有效处理大量的连接且随着连接数增加性能基本保持稳定。 事件驱动 epoll 是事件驱动的只有当有事件发生时才会通知应用程序而不是轮询所有文件描述符。 支持水平触发和边缘触发 epoll 支持两种触发模式。在水平触发模式下只要有数据可读或可写就会通知应用程序而在边缘触发模式下只在状态发生变化时通知需要手动清除事件。
epoll 的工作原理
创建 epoll 句柄 应用程序通过 epoll_create 创建一个 epoll 句柄。 添加文件描述符 使用 epoll_ctl 将文件描述符添加到 epoll 句柄中同时指定关注的事件类型读、写、异常等。 等待事件发生 应用程序使用 epoll_wait 等待事件发生。当文件描述符上发生关注的事件时epoll_wait 将返回同时告诉应用程序是哪些文件描述符发生了事件。 处理事件 应用程序得知有事件发生后可以执行相应的操作如读取数据、发送数据等。
epoll 和 select/poll 的区别
效率 epoll 的效率更高因为它不需要轮询所有文件描述符而是在事件发生时通知应用程序。 连接数 epoll 能够处理大规模的并发连接而 select 和 poll 的性能随着连接数的增加而下降。 触发模式 epoll 支持水平触发和边缘触发而 select 和 poll 只支持水平触发。 文件描述符管理 epoll 使用一组文件描述符来管理事件而 select 和 poll 使用单一的文件描述符集合。
epoll并发服务器思路
初始化 创建一个监听套接字该套接字用于接受客户端的连接请求。同时你需要创建一个 epoll 实例用于注册和监听套接字上的事件。
监听套接字设置为非阻塞 使用 fcntl 函数将监听套接字设置为非阻塞模式以便能够使用非阻塞 accept。
创建线程池 初始化一个线程池线程池的作用是处理具体的连接请求。线程池中的每个线程都可以处理一个独立的连接。
循环处理事件 在一个主循环中使用 epoll_wait 等待事件的发生。当有新的连接请求到达时你可以使用线程池中的一个线程来处理该连接。
处理连接 当新的连接到达时线程池中的一个线程会处理该连接。这可能涉及到接收、发送数据或执行其他相关任务。
使用线程池的好处 线程池可以帮助你充分利用系统的多核心资源提高并发处理能力。每个线程独立处理一个连接避免了在单线程中处理所有连接时的性能瓶颈。
注意线程安全 在处理连接时需要确保线程安全性。可以使用互斥锁等机制来保护共享资源以防止多个线程同时访问导致的问题。
重点代码分析
这部分没有展示具体的实现代码而是把一些业务逻辑省略掉了只展示了epoll和线程池相关的核心代码具体实现代码见git仓库。
初始化 创建一个监听套接字使用 epoll_create 创建一个 epoll 句柄以及一个线程池。
int listen_sock socket(AF_INET, SOCK_STREAM, 0);
// 设置 listen_sock 为非阻塞
fcntl(listen_sock, F_SETFL, fcntl(listen_sock, F_GETFL, 0) | O_NONBLOCK);
epoll_fd epoll_create(MAX_EVENTS); // MAX_EVENTS 是事件表的大小
ThreadPool pool(NUM_THREADS); // NUM_THREADS 是线程池的大小绑定和监听 将监听套接字绑定到指定地址并开始监听。
struct sockaddr_in server_addr;
// 设置 server_addr
bind(listen_sock, (struct sockaddr*)server_addr, sizeof(server_addr));
listen(listen_sock, SOMAXCONN);添加监听套接字到 epoll 事件表中
struct epoll_event ev;
ev.events EPOLLIN | EPOLLET; // 设置边缘触发模式
ev.data.fd listen_sock;
epoll_ctl(epoll_fd, EPOLL_CTL_ADD, listen_sock, ev);事件循环 使用 epoll_wait 等待事件的发生根据不同的事件类型执行相应的操作。
while (true) {struct epoll_event events[MAX_EVENTS];int num_events epoll_wait(epoll_fd, events, MAX_EVENTS, -1);for (int i 0; i num_events; i) {if (events[i].data.fd listen_sock) {// 处理新连接handle_new_connection(listen_sock);} else {// 处理其他事件pool.enqueue(handle_event, events[i].data.fd);}}
}线程池处理事件 每个事件都由线程池中的线程来处理这样可以充分利用多核 CPU 的性能。
void handle_event(int client_sock) {// 处理读写事件例如接收数据、发送数据等// 可以根据业务需要在这里进行具体的操作
}git地址
https://gitee.com/xinquanfu/epoll-chat
参考书目
Stevens, W. R., Fenner, B., Rudoff, A. M. .《UNIX网络编程 卷1: 套接字联网API》. Chen, S. 《Linux多线程服务端编程使用muduo C网络库》. 游双. 《Linux高性能服务器编程》. 莫烦周. 《深入理解Linux内核》. 云天励.《Linux性能优化实战》. Stevens, W. R. 《TCP/IP详解 卷1协议》. Richter, J. M. 《C网络编程构建高效且灵活的网络系统》.