非阻塞套接字上的select(),recv()和EWOULDBLOCK

时间:2009-05-26 16:25:20

标签: c++ c sockets

我想知道以下情况是否真实?!

  1. 非阻塞TCP套接字上的select()(RD)表示套接字已准备就绪
  2. 以下recv()将返回EWOULDBLOCK,尽管调用了select()

8 个答案:

答案 0 :(得分:4)

对于recv(),您将获得EAGAIN而不是EWOULDBLOCK,是的,这是可能的。由于您刚刚使用select()进行了检查,因此发生了以下两种情况之一:

  • 其他内容(另一个主题)已经在select()recv()之间耗尽了输入缓冲区。
  • 在套接字上设置了接收超时,它已过期,但未收到数据。

答案 1 :(得分:3)

我知道在一个流行的桌面操作中出现错误,其中O_NONBLOCK TCP套接字,特别是那些通过环回接口运行的套接字有时可能会在EAGAIN之后从recv()返回select()报告套接字已准备好阅读。在我的情况下,这发生在另一方半关闭发送流之后。

有关详细信息,请参阅我的OCaml网络应用程序环境分发版的NX库中t_nx.ml的源代码。 (link

答案 2 :(得分:3)

在Linux上,它甚至记录了这可能发生,正如我读到的那样。

看到这个问题:

Spurious readiness notification for Select System call

答案 3 :(得分:1)

这是可能的,但仅限于您有多个线程/进程尝试从同一套接字读取的情况。

答案 4 :(得分:0)

虽然我的应用程序是单线程应用程序,但我注意到所描述的行为在RHEL5中并不罕见。 TCP和UDP套接字都设置为O_NONBLOCK(设置的唯一套接字选项)。 select()报告套接字已准备就绪,但以下recv()返回EAGAIN。

答案 5 :(得分:0)

是的,这是真实的。这是它发生的一种方式:

将来对TCP协议的修改将增加一方能够“撤消”它发送的信息的功能,前提是另一方的应用层尚未接收到该信息。此功能在连接上协商。另一端向您发送一些数据,您得到select的成功。在调用recv之前,另一端将使用此新扩展名“撤消”数据。您的read收到“将被阻止”错误,因为没有数据可供读取。

select函数是状态报告函数,不附带将来的保证。假设现在击中select可以确保后续操作不会像使用其他任何状态报告功能一样无效。就像使用access来确保后续操作不会因权限错误而失败,或者使用statfs来确保后续的写入操作不会因磁盘已满而失败一样。< / p>

答案 6 :(得分:-1)

在多线程环境中,有两个线程正在从套接字读取数据。这是一个多线程应用程序吗?

答案 7 :(得分:-1)

如果你没有在这个套接字上调用select()和recv()之间的任何其他系统调用,那么recv()永远不会返回EAGAIN或EWOULDBLOCK。

我不知道它们对recv-timeout意味着什么,但是,POSIX标准在这里没有提到它,所以你可以安全地调用recv()。