【问题标题】:Non blocking TCP write(2) succeds but the request is not sent非阻塞 TCP write(2) 成功但请求未发送
【发布时间】:2009-02-25 08:07:44
【问题描述】:

我看到一小部分使用 write(2) 写入非阻塞 TCP 套接字的消息在源接口上看不到,也没有被目标接收到。

可能是什么问题?应用程序有什么方法可以检测到这一点并重试?

while (len > 0) {
    res = write (c->sock_fd, tcp_buf, len);
    if (res < 0) {
      switch (errno) {
        case EAGAIN:
        case EINTR:
        <handle case>
        break;
        default:
        <close connection>
      }
    }
    else {
      len -= res;
    }
}     

【问题讨论】:

  • 你能把代码贴在这儿还是在粘贴箱里?
  • while (len > 0) { res = write (c->sock_fd, tcp_buf, len); if (res break;默认值: }
  • 在你的 else 部分你也应该做tcp_buf = ((char*)tcp_buf) + res;
  • 我仍然看到问题。在大约 1000 个请求中,有 4 个请求没有到达套接字。
  • 在我的回答中检查关于短期套接字的编辑。

标签: tcp nonblocking


【解决方案1】:

非阻塞write(2) 意味着无论遇到什么困难,电话都会返回。检测发生了什么的正确方法是检查函数的返回值。

如果返回 -1,请检查 errnoEAGAIN 的值表示 write 没有没有发生,你必须再做一次。

它还可能返回一个短写入(即一个小于您传递给它的缓冲区大小的值),在这种情况下,您可能需要重试丢失的部分。

如果这种情况发生在短寿命套接字上,请阅读The ultimate SO_LINGER page, or: why is my tcp not reliable。它解释了有关传输关闭部分的特定问题。

当我们天真地使用 TCP 来发送我们需要传输的数据时,它通常无法完成我们想要的 - 最终传输的千字节或有时兆字节的数据永远不会到达。

结论是:

最好的建议是发送长度信息,并让远程程序主动确认已收到所有数据。

它还描述了一种针对 Linux 的 hack。

【讨论】:

  • 我看到无论我要求写什么,写都成功了。我确实检查了返回值和 EAGAIN。返回值是我要求写的长度
【解决方案2】:

write() 返回写入的字节数,这可能小于你发送的字节数,甚至为 0!确保检查并重新传输丢弃的任何内容(由于 NIC 上没有足够的缓冲区空间或其他原因)

【讨论】:

  • 我会检查返回的字节数。它返回的字节数与我要求写入的字节数相同。但是界面上仍然没有看到请求
【解决方案3】:

您想了解TCP_NODELAY 选项和 TCP 发送缓冲区的性质。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-02-09
    • 2012-11-30
    • 2013-11-12
    • 2014-08-15
    • 2012-10-28
    • 2014-11-01
    • 2021-08-28
    • 2020-03-04
    相关资源
    最近更新 更多