我的linux应用程序正在执行非阻塞TCP连接系统调用,然后使用epoll_wait
来检测三次握手完成。
有时epoll_wait
会同时返回POLLOUT
&为同一套接字描述符设置的POLLERR
事件。
我想了解TCP级别的情况。我无法按需复制它。我的猜测是,在我的事件循环内两次调用epoll_wait
之间,我们有一个SYN + ACK / ACK / FIN序列,但我再也无法重现它。
答案 0 :(得分:6)
如果连接失败,可能会发生这种情况 - 例如“连接超时”(对于执行非阻塞连接的套接字,当连接操作完成时,POLLOUT
将成功设置和不成功的结果)。
当为套接字设置POLLOUT
时,使用getsockopt(sock, SOL_SOCKET, SO_ERROR, ...)
检查连接是否成功(在这种情况下SO_ERROR
套接字选项为0,否则指示连接的原因失败)。
答案 1 :(得分:4)
以下是non-blocking tcp connect()的一些很好的信息。
当检测到套接字错误(即连接关闭/拒绝/超时)时,epoll将使用POLLERR返回已注册的兴趣事件POLLIN / POLLOUT。因此,如果你注册了POLLOUT,epoll_wait()将返回POLLOUT | POLLERR,如果注册POLLIN | POLLOUT,则返回POLLIN | POLLOUT | POLLERR。
仅仅因为epoll返回POLLIN并不意味着可以读取数据,因为recv()可能只是从非阻塞connect()调用返回错误。我认为epoll使用POLLERR返回所有已注册的事件,以确保程序调用send()/ recv()/ etc ..并获得套接字错误。有些程序从不检查POLLERR / POLLHUP,只在下一次send()/ recv()调用时捕获套接字错误。