我正在使用 select()
从 TCP 套接字进行非阻塞 read()
。当 select()
指示有数据可供读取时,我不确定在 read()
之后是否还需要处理 EINTR
。
最佳答案
是的,绝对是。 select
函数是一个状态报告函数,它会在您调用 select
和您注意到它的返回值之间的某个时间报告某物的状态。它绝对没有任何 future 保证。
这是一个非常普遍的误解。但是认为 select
确保 future 的操作将提供某些特定结果的想法与认为检查磁盘上是否有可用空间意味着 future 的写入不会失败一样是错误的。根据其判断,即使您认为有足够的可用空间,该实现也允许在可用空间不足的情况下使写入失败。并且可以在找到空间和尝试使用它之间填充空间。
select
也是如此。没有规则要求实现必须以某种方式记住它给了你 select
的命中并且影响了后续读取的实现。人们已经多次做出这种假设,并被它可怕地咬伤了。不要仅仅因为您想不出它会失败的任何方式就认为它不会失败。
例如,没有规则禁止实现执行以下操作:
- 收到一个数据包。
- 它是有效的 TCP 数据,所以
select
返回准备读取。此时发出的read
将返回数据。 - 在实现可以确认数据之前,网络接口(interface)的写入队列已满。
- 由于实现发现由于队列已满而无法立即发送 ACK,因此它只是选择丢弃数据包并强制另一端重新传输
- 由于没有数据可读,后续的
read
操作将被阻塞。
如果您认为某些标准禁止它,请引用该标准。 select
命中后的 read
可能因任何原因而失败 select
命中前的 read
可能会失败。 select
函数never 提供 future 保证。
关于c - TCP 套接字 : Can read() still fail with EINTR when select() indicates there are data available?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48959061/