前言
本文介绍解决accpet和recv相互阻塞的问题,可以用多线程并发外也可以用epoll I/O多路复用的方式解决。
epoll I/O多路复用
I/O多路复用原理
因为accept和recv相互阻塞,并且无法确定那个函数先执行,所以代码无法直接写
accept阻塞是sockfd带来饿,recv阻塞是newfd带来的
核心思想:所以需要一个工具,将sockfd和newfd统一监管,哪个fd发生了事件(连接事件和收数据事件),就把哪个fd通知给用户,用户程序再调用对应的处理函数去处理。
多路IO复用的方法:select、poll、epoll
select poll epoll的区别(重点)
select和poll是轮询模式(顺序查找,全过一遍)
epoll是事件(告诉谁需要先处理,哈希查找)
select | poll | epoll | |
监控机制 | 线性表遍历方式 | 同select,解决了select文件描述符数量的限制 | 基于事假 |
性能 | 当文件描述符数量增加时,性能线性下降 | 同select,但没有文件描述符数量的限制 | 性能不随监控的文件描述符数量增加而显著下降,适合大规模文件描述符的监控 |
最大文件描述符数量 | 有限制,通常为1024 | 无硬性限制,但大量文件描述符会导致性能下降 | 无硬性限制,理论上受内存大小限制 |
可移植性 | 跨平台,广泛支持 | 跨平台,广泛支持 | 主要在Linux系统中支持,其它系统的支持不高 |
epoll工作原理
epoll相关函数
epoll_create函数
#include <sys/epoll.h>
int epoll_create(int size);
//例子
int epfd = epoll_create(10);
功能:创建epoll
参数:大于0即可,epoll能存储的fd个数是动态增加的
返回值:≥0 代表epoll的文件描述符,<0 创建失败
epoll_ctl函数
#include <sys/epoll.h>
int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event);
功能:向epoll中添加/删除一个fd
参数1:epoll_create的返回值
参数2:EPOLL_CTL_ADD 添加
EPOLL_CTL_DEL 删除
参数3:待添加的文件描述符fd
参数4:待添加fd的相关属性