Epoll和远程单向关闭

13
假设本地Linux主机上的TCP套接字处于已连接状态,并且正在使用epoll_wait来通知本地主机与远程主机之间的套接字事件。如果远程主机调用:
 shutdown(s,SHUT_WR);

当一个连接的套接字完成传输时,在本地主机上,epoll_wait会返回哪些事件来指示它已完成传输?

我假设EPOLLIN总是被返回,并且随后的recv调用将返回0以指示远程方已经完成传输。

那么EPOLLHUP或EPOLLRDHUP呢?这两个事件有什么区别?

EPOLLERR呢?

如果远程主机调用"close"而不是"shutdown",上述任何答案是否会改变?

1个回答

23

我在查找答案之后自己回答了这个问题。

监听 epoll 事件的套接字通常会收到 EPOLLRDHUP(除了 EPOLLIN)事件标志,表示远程对等方调用 close 或 shutdown(SHUT_WR)。这并不一定意味着套接字已经失效。随后对 recv() 的调用将返回套接字上的任何未读数据,并最终返回“0”,表示已达到文件结束。如果远程对等方仅针对其套接字进行了半关闭,甚至可以发送数据回去。

唯一需要注意的例外是,如果远程对等方使用启用了 linger 值为“0”的 SO_LINGER 选项,则关闭此类套接字的结果可能会导致发送 TCP RST 而不是 FIN。据我所读,连接重置事件将生成 EPOLLHUP 或 EPOLLERR(虽然我还没有时间确认,但这是有道理的)。

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

就我个人而言,在我的特定情况下,编写特别处理 EPOLLHUP 或 EPOLLRDHUP 事件的代码并不是很有趣。相反,只需将这些事件视为 EPOLLIN/EPOLLOUT 并调用 recv()(或适当的 send())。但要特别注意从 recv() 和 send() 返回的返回值。


1
我对此行为有更多的问题,因此我进行了详细的深入研究这些交互:https://medium.com/where-the-flamingcow-roams/down-the-epoll-rabbit-hole-5c0447cb6329 - flamingcow

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接