假设本地linux主机上的TCP套接字与远程主机处于连接状态。本地主机正在使用epoll_wait通知远程主机的套接字上的事件。
如果要拨打远程主机:
shutdown(s,SHUT_WR);
在其连接的套接字上表示它已完成传输,epoll_wait会在本地主机上为其套接字返回什么事件?
我假设EPOLLIN总是会返回,后续的recv调用将返回0表示远程端已完成传输。
EPOLLHUP或EPOLLRDHUP怎么样? (这两个事件之间有什么区别)?
甚至是EPOLLERR?
如果远程主机呼叫“关闭”而不是“关闭”,上述任何一个的答案都会改变吗?
答案 0 :(得分: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()返回的返回码。