问题:epoll和远程1路关机

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

如果远程主机要调用:

 shutdown(s,SHUT_WR);

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

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

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

甚至是 EPOLLERR ?

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

解答

在完成繁重的工作以找到答案后,我自己回答了这个问题。

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

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

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

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

Logo