1.使用I/O复用的情况
- 客户端程序要同时处理多个套接字
- 客户端程序要同时处理用户输入和网络连接
- TCP服务器要同时处理监听套接字和连接套接字
- 服务器要同时处理TCP请求和UDP请求
- 服务器要同时监听多个端口,或者处理多种服务
2.epoll系统调用
- 创建内核事件表
int epoll_create(int size)
- size:提示内核,事件表的大小
- 返回值:文件描述符,指向内核事件表
- 向内核事件表中添加/修改/删除事件
int epoll_ctl(int epfd,int op,int fd,struct epoll_event* event)
struct epoll_event
{
_unit32_t events;//epoll事件
epoll_data_T data;//用户数据
};
- epfd:指向内核事件表的文件描述符
- op:指定操作类型 (如下表)
- fd:要操作的文件描述符
- event:事件类型(如下表)
- 返回值:成功返回0,失败返回-1并设置errno
操作类型 | 作用 |
---|---|
EPOLL_CTL_MOD | 修改fd上的注册事件 |
EPOLL_CTL_ADD | 往事件表中注册fd上的事件 |
EPOLL_CTL_DEL | 删除fd上的注册事件 |
事件类型 | 作用 |
---|---|
EPOLLIN | 可读事件 |
EPOLLRDNORM | 普通数据可读 |
EPOLLOUT | 数据可写 |
EPOLLRDHUP | TCP连接被对方关闭,或者对方关闭了写操作触发该事件,需要定义 _GNU_SOURCE |
EPOLLERR | 错误 |
EPOLLHUP | 挂起 |
EPOLLET | 开启ET模式 |
EPOLLONESHOT | ET模式时,在epoll上注册事件 |
- 获取就绪描述符
int epoll_wait(int epfd,struct epoll_event* events,int maxevents,int timeout);
- epfd:指向内核事件表的文件描述符
- events:若函数检测到事件,就将就绪事件从内核事件表复制到events指向的数组中
- maxevents:指定最多监听的事件数量
- timeout:指定epoll的超时值,单位为毫秒。当值为-1时,epoll_wait 阻塞,直到某个事件发生;当值为0时,epoll_wait 立即返回
- 返回值:成功时返回就绪描述符的个数,失败返回-1并设置 errno
3.代码实现
int create_socket()//创建监听套接字
{
int sockfd = socket(AF_INET,SOCK_STREAM,0);
if(sockfd==-