我知道如果远程主机正常关闭连接,则epoll
将报告EPOLLIN
,并且调用read
或recv
不会阻塞,并且将返回0字节(即流的末尾)。
但是,如果未正常关闭连接,并且write
或send
操作失败,这是否会导致epoll
随后为该套接字返回EPOLLIN
,从而产生相同/相似的流结束情况?
我试图找到有关此行为的文档,但没有成功,尽管可以测试,但我对具有特定内核版本的特定发行版上发生的情况不感兴趣。
最佳答案
实际上,从规范中并不能完全看出这一点,但是对于poll()
,它的工作方式如下:
如果有可供读取的数据,即使连接已关闭,也会返回POLLIN
。
如果由于关闭连接而无法进行读取或写入,则返回POLLHUP
或POLLERR
。
如果不再可以读取但可以进行写入(例如,另一端执行了shutdown(SHUT_WR)
),则返回POLLIN
,并且不返回POLLHUP
和POLLERR
。 (这允许正常等待POLLOUT
。)
简单的事情是在设置POLLIN
,POLLHUP
和POLLERR
中的任何一个时尝试读取。
在kqueue()
中,可能仅触发一个EVFILT_READ
过滤器。手册页中对此进行了描述,应该足够清楚。
请注意,如果您没有启用TCP keepalive(FreeBSD默认启用了它们,而大多数其他操作系统则没有启用),那么如果网络以某种方式中断,等待数据读取可能会永远陷入困境。即使启用了TCP keepalive,也往往需要花费几个小时才能检测到断开的连接。