poll() 在以 0 超时调用时接收传入数据

Posted

技术标签:

【中文标题】poll() 在以 0 超时调用时接收传入数据【英文标题】:poll() ingores incoming data when called with 0 timeout 【发布时间】:2013-12-02 21:28:07 【问题描述】:

我的应用程序通过零超时调用 poll() 来检查 TCP 套接字中的传入数据。 99% 的时间它都可以正常工作,当套接字上有数据时,它会设置 POLLIN 标志。但是有时套接字上有数据(我在 wireshark 上看到消息),但 poll() 返回 0(超时)并且不设置 POLLIN 标志。当另一条消息到来时,它会在几秒钟后设置 POLLIN 标志。

这是正常行为吗? poll() 是否总是在超时前至少检查一次传入数据?

根据answers in another question,Linux 手册页对此不是很清楚。

【问题讨论】:

您确定您看到的是完整的数据,即不是先前数据丢失的 TCP 数据段,因此 TCP 堆栈正在等待重新传输?或者如果是 UDP,UDP 数据包可能会被丢弃? 你能提供一个带有 poll() 调用的代码 sn-p 吗? poll for POLLIN 超时时间为零意味着不超过“查看接收缓冲区中是否有我可以立即读取的任何(有效)数据,否则立即返回” 。这并不意味着“验证是否有任何数据报到达网络”或任何其他事情。您是否验证过数据报的校验和对于 Wireshark 看到的这些数据报有效,并且它们不是例如重发?在这种情况下 Poll 显然不会报告 POLLIN,因为接收缓冲区中不会放置任何内容。 Linux 联机帮助页(在我看来)也非常清楚。 poll 从不检查传入数据,它检查传入的数据(是的,它总是只检查一次(不是更频繁)或 它会在您指定的时间内阻塞)。 【参考方案1】:

我在 poll() 中以 10 毫秒的超时时间重现了该错误。经过进一步调查,我发现问题是由包装 unix 套接字 API 的库中的错误引起的。它正在将数据从套接字加载到缓冲区中,然后在消耗缓冲区中的所有字节之前轮询套接字以获取更多数据。无论如何感谢 cmets。

因此,即使超时为 0,poll() 似乎也能正常工作。

【讨论】:

以上是关于poll() 在以 0 超时调用时接收传入数据的主要内容,如果未能解决你的问题,请参考以下文章

I/O复用:select poll epoll相关问题

NSRunLoop 阻塞传入数据

如何在没有超时/死锁的情况下在PROMELA进程中发送和接收?

如何在 erlang gen_server 中有效地使用接收子句来解决超时错误?

Ansible 的委托 并发和任务超时

Linux内核中网络数据包的接收-第二部分 select/poll/epoll