【问题标题】:Does recv(...) operate this way?recv(...) 是否以这种方式运行?
【发布时间】:2014-01-04 06:35:09
【问题描述】:

我正在使用SO_RCVTIMEO 将套接字的超时设置为 10 秒。这个问题特定于流套接字(TCP)。当我从手册页中收集到的信息中调用 recv(...) 时,这就是我所期待的:

  1. 如果远程关闭连接,无论超时,它都会立即返回 0。
  2. 如果超时到期并且没有接收到数据,那么我们会返回 -1 和 EAGAINEWOULDBLOCK 中的 errno
  3. 如果套接字发生错误,它会立即返回 -1,然后正确设置 errno
  4. 如果数据可用,则套接字会等待直到发生超时,然后再返回。这次它将在 10 秒内返回接收到的总字节数。

这是正确的行为吗?我只是想确保我正确理解文档。

谢谢! 布雷特

【问题讨论】:

    标签: c sockets posix recv


    【解决方案1】:

    差不多。

    有一个警告:如果你设置MSG_WAITALL,至少有一个实现(FreeBSD)在每次一些数据到达时重新启动计时器。例如,如果您向recv 请求 8192 个字节并且一个字节到达,the timer is reset。如果另一个字节在 10 秒内到达,定时器将再次复位。因此,如果字节每 5 秒滴入一个,您将等待 (8191 * 5) = 40955 秒 = 超过 11 小时,recv 最终返回 8192。(如果在 EOF 之前没有足够的字节到达,recv 将失败,@987654327 @.)

    文档暗示(至少对我而言)即使没有 MSG_WAITALL 也会发生这种情况,但测试表明此警告仅适用于 MSG_WAITALL 案例。

    【讨论】:

    • 说实话 - 很难想象。通常,我希望 FreeBSD 符合其他实现,并在一些数据可用时立即返回。
    • @glglgl:我承认我没有测试过它,但这就是手册页所声称的。好像有点破:-)
    • 在所有情况下?我只是 read 关于触发此行为的 recv() 选项 MSG_WAITALL...
    • @glglgl:对源代码的快速扫描表明这是一个惰性实现。 sbwait() 使用so_timeo 中的值,并且接收循环落入sbwait, then goto restart,除非您设置MSG_DONTWAITMSG_NBIO(或套接字本身设置SS_NBIO)。如果需要,您可以设置高水位标记 (so_rcv.sb_hiwat) 以提前停止等待。
    • 这是不正确的。如果在超时时间内有一个字节到达,recv() 返回,返回值为 1。如果你再次调用它,定时器当然会被重置。 recv() 没有尝试“最终返回 8192”。
    【解决方案2】:
    1. 正确。
    2. 有两种不同的规格(遗憾的是我目前无法测试)
      2.1 ETIMEOUT 将被返回。 (如果没有立即可用的数据,则在非阻塞套接字上返回EAGAINEWOULDBLOCK。)http://pubs.opengroup.org/onlinepubs/9699919799/functions/recv.html
      2.2 EAGAINEWOULDBLOCK 将返回 2.1 http://man7.org/linux/man-pages/man2/recvmsg.2.html 下提到的两种可能性
    3. 正确。
    4. 如果读取了至少 1 个字节,则套接字可能会随时返回,即使读取的内容少于然后告知超时并且超时尚未到期。

    【讨论】:

    猜你喜欢
    • 2021-07-19
    • 1970-01-01
    • 2016-03-09
    • 2016-04-09
    • 1970-01-01
    • 2016-02-02
    • 1970-01-01
    • 2019-10-20
    • 1970-01-01
    相关资源
    最近更新 更多