【问题标题】:How is it possible to have send timeout on a non blocking socket?如何在非阻塞套接字上设置发送超时?
【发布时间】:2012-11-13 11:09:25
【问题描述】:

我在理解 Linux 中套接字的工作时遇到了一些问题。

setsockopt(sockfd, SOL_SOCKET, SO_SNDTIMEO, &timeout, sizeof(int));
write = write(sockfd, buf, len);

在上面的代码中,由于写入被缓冲,发送超时没有任何意义(当用户空间缓冲区被复制到内核缓冲区时,写入系统调用将立即返回)。发送缓冲区大小是更重要的参数,但发送超时似乎没有任何价值。但我肯定错了,因为我见过很多使用 SO_SNDTIMEO 的代码。假设接收器很慢,用户空间代码如何使用 SO_SNDTIMEO 超时?

【问题讨论】:

  • 你能说明你想要达到什么结果吗?
  • 没有我想要达到的结果,我问这个问题是为了了解套接字的工作原理,特别是为什么 SO_SNDTIMEO 甚至存在?
  • 这个答案可能会帮助你理解 SO_SNDTIMEO:stackoverflow.com/a/4182564/10682
  • @Alexey Feldgendler - 这是一个有效的问题。如果 SO 仅限于“实用”,他们将不得不删除 20% 的问题。这里有很多令人麻木的晦涩问题。
  • 我能想到在非阻塞套接字上设置SO_SNDTIMEO 的唯一原因是,在代码库的某个地方,套接字被设置回阻塞模式(可能只是临时用于特定操作) , 并且代码的作者希望套接字在设置回阻塞模式的时间内超时。 (或者,很可能,应用程序最初是为使用阻塞模式套接字而编写的,后来被转换为使用非阻塞套接字,而代码作者只是忘记取出现在不必要的 SO_SNDTIMEO 调用)

标签: sockets network-programming setsockopt


【解决方案1】:

SO_SNDTIMEO 对于阻塞套接字很有用。如果套接字的缓冲区已满,则 send() 可以阻塞,在这种情况下,使用 SO_SNDTIMEO 套接字选项可能很有用。对于非阻塞套接字,如果套接字的缓冲区已满,发送将立即失败,因此将 SO_SNDTIMEO 设置为非阻塞套接字是没有意义的。

【讨论】:

    【解决方案2】:

    如何在非阻塞套接字上设置发送超时?​​

    不是。超时用于阻塞模式。非阻塞 recv() 不会阻塞,因此也不会超时。

    我见过很多使用 SO_SNDTIMEO 的代码。

    除非相关代码是无意义的,否则不处于非阻塞模式。

    【讨论】:

    • 在 linux 中如何确保发送或写入数据包是阻塞的,即。 write 或 send 仅在内核收到整个缓冲区长度的 ACK 时才返回(缓冲区将分解为多个 tcp 数据包)
    • @mc_87 你不能。如果您需要确认,您必须自己在应用程序级别发送一个。
    • 那么,如果在应用程序级别我不能阻塞直到我最后一次 tcp ack,那么 SO_SNDTIMEO 将如何有用?
    • @mc_87 当您发送到一个完整的套接字发送缓冲区或接收到一个空的套接字接收缓冲区时,在阻塞模式下发生的块超时。发送时等待 ACK 的部分只是您的想象。 TCP 是流协议,而不是请求/响应协议。
    猜你喜欢
    • 1970-01-01
    • 2012-09-15
    • 1970-01-01
    • 1970-01-01
    • 2012-11-26
    • 2010-09-22
    • 2013-06-04
    • 2010-11-04
    • 2019-07-10
    相关资源
    最近更新 更多