c - TCP 套接字 : Can read() still fail with EINTR when select() indicates there are data available?

标签 c sockets tcp network-programming kernel

我正在使用 select() 从 TCP 套接字进行非阻塞 read()。当 select() 指示有数据可供读取时,我不确定在 read() 之后是否还需要处理 EINTR

最佳答案

是的,绝对是。 select 函数是一个状态报告函数,它会在您调用 select 和您注意到它的返回值之间的某个时间报告某物的状态。它绝对没有任何 future 保证。

这是一个非常普遍的误解。但是认为 select 确保 future 的操作将提供某些特定结果的想法与认为检查磁盘上是否有可用空间意味着 future 的写入不会失败一样是错误的。根据其判断,即使您认为有足够的可用空间,该实现也允许在可用空间不足的情况下使写入失败。并且可以在找到空间和尝试使用它之间填充空间。

select 也是如此。没有规则要求实现必须以某种方式记住它给了你 select 的命中并且影响了后续读取的实现。人们已经多次做出这种假设,并被它可怕地咬伤了。不要仅仅因为您想不出它会失败的任何方式就认为它不会失败。

例如,没有规则禁止实现执行以下操作:

  1. 收到一个数据包。
  2. 它是有效的 TCP 数据,所以 select 返回准备读取。此时发出的 read 将返回数据。
  3. 在实现可以确认数据之前,网络接口(interface)的写入队列已满。
  4. 由于实现发现由于队列已满而无法立即发送 ACK,因此它只是选择丢弃数据包并强制另一端重新传输
  5. 由于没有数据可读,后续的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/

相关文章:

c - 链表内存图

c - 在 C 中立即(逐个数据包)从套接字接收 TCP 有效负载

ios - GCDAsyncSocket是否可以自动读取数据

c - 编程错误 - 名称被截断,无法将参数 1 从 'int' 转换为 'char *'

c - 绑定(bind)到两个本地 IP 失败

linux - SO_REUSEPORT 与多播 UDP 的使用

linux - 获取内核中套接字事件的通知

http - 如何重新组装tcp段?

c++ - QTcpSocket - 扩展 QRunnable 时指定了无效句柄

java - 从套接字的 byte[] 开头解析 int