2017-01-16 78 views
0

我的应用程序类似于libevent,使用epoll(在级别触发模式下)来检测I/O活动并调用回调来处理它。当epoll发出信号时,recv()调用会如何阻止?

我最近发现,我的TCP/IP套接字被阻塞,这是一个意外,但我仍然不希望recv()调用阻止FD被epoll报告为有读取活动挂起。即使插座出现错误,当然recv()会返回并告诉我。

我对此有什么误解?
在这种情况下,什么样的网络状况可能导致recv()阻塞?

+0

您是否已将'MSG_WAITALL'传递给'recv()'?在这种情况下,即使某些(但不是全部)字节可能已经可用,该功能可能会阻止。 –

+0

@RalphTandetzky:编号''recv(fd,buf,BUFSIZE,0);' –

+2

通常会发生这种情况,因为epoll + recv不是原子的,所以如果epoll和recv之间发生其他事情,套接字可能不再准备好在你打电话给recv的时候阅读。但是,如果没有[MVCE](http://stackoverflow.com/help/mcve),就不可能说出你的情况可能会发生什么。 –

回答

1

在Linux select手册页:

在Linux下,选择()可能会报告套接字文件描述符为“准备 阅读”,而不过随后的读取块。这个 可能例如发生在数据已经到达但是在检查时 具有错误的校验和并被丢弃。可能有其他 情况,其中文件描述符虚假地报告为 就绪。因此,在应该不会阻塞的套接字上使用O_NONBLOCK可能更安全。

(是的,我知道的epoll()是不一样的选择(),但我怀疑相同的基础条件适用于)

我认为,如果你真的想避免阻塞,唯一安全的方法是将你的套接字设置为非阻塞模式。

+0

啊哈 - 这可能是。谢谢:) –

0

如果您使用Epoll来轮询EPOLLIN事件,那么之后的recv调用应立即返回。此外,我希望你正在使用非阻塞套接字。如果你想查找错误,那么你可以查找EPOLLERR事件。如果套接字在epoll信号后关闭,则recv应该失败。 epoll_wait,epoll_ctl和套接字创建的代码片段将有助于调试问题。