给定任何epoll TCP套接字事件,如果EPOLLRDHUP = 0且EPOLLIN = 1; 是对read()/ recv()的后续调用,保证返回不等于0的读取大小?

Wil*_*ill 6 c sockets linux epoll tcp

从epoll_ctl的手册:

EPOLLRDHUP(自Linux 2.6.17起)

流套接字对等关闭连接,或关闭写入一半的连接.(此标志对于编写简单代码以在使用边缘触发监视时检测对等关闭特别有用.)

从recv手册:

如果没有可用的消息被接收并且对等体已经执行了有序关闭,则recv()将返回0.

在我看来,那么,以上的盖的同一场景,只要我抓住EPOLLRDHUP事件首先,我不应该收到read()或长度为零的recv()(因此不需要费心检查这样的).但这是否保证是真的?

Rem*_*eau 7

如果你得到一个事件EPOLLRDHUP=1然后立即关闭连接而不阅读.如果你得到一个事件EPOLLRDHUP=0,并EPOLLIN=1再继续读,但你应该准备处理的可能性recv()仍然返回0,以防万一.也许是FIN在你到达之后EPOLLIN=1但在你实际打电话之前到达的recv().

  • "也许FIN在你获得EPOLLIN = 1但在你实际调用recv()之前到达." 但即使FIN到达这样的时刻,recv()也会返回大于0的东西,对吧?因为FIFO管道仍然包含首先引发的EPOLLIN = 1. (3认同)
  • 我不同意这个答案。我认为“如果您收到 EPOLLRDHUP=1 的事件”的部分是错误的,因为我碰巧同时获得 EPOLLIN 和 EPOLLRDHUP,如果对等方发送了一些东西并立即关闭了连接。所以,有数据要读取。 (2认同)
  • @haelix我现在正在查看,可以确认这一点。在本地主机上的快速写入/关闭将导致0x2001(RDHUP | IN),但管道中有数据,并且读取将首先返回数据,然后返回零。同样,例如,SIGPIPE将导致0x2019(RDHUP | HUP | ERR | IN)的读取返回零。在这种情况下,您可以跳过读取操作,而只对RDHUP进行操作,但是在上述情况下,您可能希望发送数据,这在我看来使RDHUP变得毫无用处,因为在读取时无论如何您都需要处理此问题。 (2认同)