Epoll 相关

EPOLLHUP (which signals an unexpected close of the socket, i.e. usually an internal error).

EPOLLRDHUP   正常断开。

EPOLLIN     //表示对应的文件描述符可以读(包括对端SOCKET正常关闭);

EPOLLOUT    //表示对应的文件描述符可以写;

EPOLLPRI    //表示对应的文件描述符有紧急的数据可读(这里应该表示有带外数据到来);

EPOLLERR    //表示对应的文件描述符发生错误;

EPOLLET     //将EPOLL设为边缘触发(Edge Triggered)模式,这是相对于水平触发(Level Triggered)来说的。

EPOLLONESHOT//只监听一次事件,当监听完这次事件之后,如果还需要继续监听这个socket的话,需要再次把这个socket加入到EPOLL队列里。


//Epoll 判定client端断开

当客户端使用ctrl+c强制中断或者强制退出时,服务器端希望能够检测到这一变化,我一般是使用检测read是否返回0来判断。但是会出现这样的情况,当使用ctrl+c时,epoll可以收到EPOLLIN事件,并用read返回0;但是当客户端正常退出时,则检测不到该变化。tcpip

有人试图使用EPOLLHUP来完成这一检测,实际上EPOLLHUP不能用于服务器来检测客户端出现的异常,但EPOLLRDHUP是可以的。

在使用 epoll 时,对端正常断开连接(调用 close()),在服务器端会触发一个 epoll 事件。在低于 2.6.17 版本的内核中,这个 epoll 事件一般是 EPOLLIN,即 0x1,代表连接可读。连接池检测到某个连接发生 EPOLLIN 事件且没有错误后,会认为有请求到来,将连接交给上层进行处理。这样一来,上层尝试在对端已经 close() 的连接上读取请求,只能读到 EOF,会认为发生异常,报告一个错误。

因此在使用 2.6.17 之前版本内核的系统中,我们无法依赖封装 epoll 的底层连接库来实现对对端关闭连接事件的检测,只能通过上层读取数据时进行区分处理。不过,2.6.17 版本内核中增加了 EPOLLRDHUP 事件,代表对端断开连接,。

在使用 2.6.17 之后版本内核的服务器系统中,对端连接断开触发的 epoll 事件会包含 EPOLLIN | EPOLLRDHUP,即 0x2001。有了这个事件,对端断开连接的异常就可以在底层进行处理了,不用再移交到上层。重现这个现象的方法很简单,首先 telnet 到 server,然后什么都不做直接退出,查看在不同系统中触发的事件码。注意,在使用 2.6.17 之前版本内核的系统中,sys/epoll.h 的 EPOLL_EVENTS 枚举类型中是没有 EPOLLRDHUP 事件的,所以带 EPOLLRDHUP 的程序无法编译通过。



Note that getting a "zero bytes read" result when reading from a socket also means that the other end has shut down the connection, so you should always check for that too, to avoid nasty surprises (the FIN might arrive after you have woken up from EPOLLIN but before you call read, if you are in ET mode, you'll not get another notification).

意思是这个是时候如果你不关闭这个socket,每次读取是失败的。


所以关于检测一段关闭的方式EPOLLRDHUP&read()==0 双重检测。


你可能感兴趣的:(Epoll 相关)