Epoll和远程单向关机

sel*_*bie 11 sockets linux epoll tcp

假设本地linux主机上的TCP套接字与远程主机处于连接状态.本地主机正在使用epoll_wait通知远程主机的套接字上的事件.

如果远程主机要打电话:

 shutdown(s,SHUT_WR);
Run Code Online (Sandbox Code Playgroud)

在其连接的套接字上,表明它已完成传输,epoll_wait将在本地主机上为其套接字返回什么事件?

我假设总是会返回EPOLLIN并且后续的recv调用将返回0以指示远程端已完成传输.

EPOLLHUP或EPOLLRDHUP怎么样?(这两个事件有什么区别)?

甚至EPOLLERR?

如果远程主机呼叫"关闭"而不是"关闭",上述任何一个的答案是否会改变?

sel*_*bie 20

我在做了繁重的工作后自己回答这个问题才找到答案.

侦听epoll事件的套接字通常会在远程对等方呼叫关闭或关闭(SHUT_WR)时收到EPOLLRDHUP(除了EPOLLIN之外)事件标志.这并不一定意味着套接字已经死了.对recv()的后续调用将返回套接字上的任何未读数据,最终将返回"0"以指示EOF.如果远程对等体仅对其套接字进行半关闭,则甚至可以发回数据.

一个值得注意的例外是远程对等方在其套接字上使用SO_LINGER选项并且延迟值为"0".关闭此类套接字的结果可能导致发送TCP RST而不是FIN.根据我的阅读,连接重置事件将生成EPOLLHUP或EPOLLERR.(我没有时间确认,但这很有意义).

有一些文档表明有较旧的Linux实现不支持EPOLLRDHUP,因此会生成EPOLLHUP.

对于它的价值,在我的特定情况下,我发现拥有特殊情况EPOLLHUP或EPOLLRDHUP事件的代码并不是太有趣.相反,只需将这些事件视为与EPOLLIN/EPOLLOUT相同,并根据需要调用recv()(或send()).但请密切关注从recv()和send()返回的返回码.