【发布时间】:2010-10-29 00:49:49
【问题描述】:
我想知道下面的场景是不是真实的?!
- 非阻塞 TCP 套接字上的 select() (RD) 表示套接字已准备就绪
- 尽管调用了 select(),但在 recv() 之后会返回 EWOULDBLOCK
【问题讨论】:
我想知道下面的场景是不是真实的?!
【问题讨论】:
对于recv(),你会得到EAGAIN 而不是EWOULDBLOCK,是的,这是可能的。由于您刚刚检查了select(),因此发生了以下两件事之一:
select() 和recv() 之间的输入缓冲区。【讨论】:
这是可能的,但仅在您有多个线程/进程试图从同一个套接字读取的情况下。
【讨论】:
【讨论】:
我知道一个流行的桌面操作中的错误,其中O_NONBLOCK TCP 套接字,特别是那些在环回接口上运行的套接字,有时可以在select() 报告套接字已准备好读取之后从recv() 返回EAGAIN .就我而言,这发生在对方半关闭发送流之后。
有关更多详细信息,请参阅我的 OCaml 网络应用程序环境分发的 NX 库中的 t_nx.ml 的源代码。 (link)
【讨论】:
虽然我的应用程序是单线程的,但我注意到所描述的行为在 RHEL5 中并不少见。使用设置为 O_NONBLOCK(唯一设置的套接字选项)的 TCP 和 UDP 套接字。 select() 报告套接字已准备好,但随后的 recv() 返回 EAGAIN。
【讨论】:
是的,这是真的。这是发生这种情况的一种方式:
未来对 TCP 协议的修改增加了一方“撤销”其发送的信息的能力,前提是该信息尚未被另一方的应用层接收。此功能是在连接上协商的。对方向你发送一些数据,你会得到一个select 命中。在您致电recv 之前,对方会使用这个新的扩展名“撤销”数据。您的 read 收到“将阻止”错误,因为没有可供读取的数据。
select 函数是一个状态报告函数,不附带未来保证。假设现在点击select 可以确保后续操作不会阻塞,这与以这种方式使用任何其他状态报告功能一样无效。就像使用access 尝试确保后续操作不会因权限错误而失败或使用statfs 尝试确保后续写入不会因磁盘已满而失败一样糟糕。
【讨论】:
在两个线程从套接字读取的多线程环境中是可能的。这是一个多线程应用程序吗?
【讨论】:
select()的参数?如果在select() 和recv() 之间发生超时怎么办?
如果您不在此套接字上的 select() 和 recv() 之间调用任何其他系统调用,则 recv() 将永远不会返回 EAGAIN 或 EWOULDBLOCK。
我不知道 recv-timeout 是什么意思,但是,POSIX 标准在这里没有提到它,所以你可以安全地调用 recv()。
【讨论】: