【问题标题】:Weird send() problem (with Wireshark log)奇怪的 send() 问题(带有 Wireshark 日志)
【发布时间】:2010-04-21 21:37:34
【问题描述】:

我还有一个关于这个问题的问题,但我没有正确地问,所以我又来了!

我通过分块发送文件来发送文件。现在,我正在为该块的大小使用不同的数字,看看哪种大小最有效。

在 localhost 上进行测试时,任何块大小似乎都可以正常工作。但是当我通过网络对其进行测试时,似乎最大块大小为 8191 字节。如果我尝试更高的东西,传输会变得非常、痛苦、缓慢。

为了说明会发生什么,这里是当我使用 8191 字节的块大小和使用 8192 字节的块大小时 Wireshark 日志的前 100 行:(发送方是 192.168.0.102,接收方是192.168.0.100)

8191:http://pastebin.com/E7jFFY4p

8192:http://pastebin.com/9P2rYa1p

请注意在 8192 日志中的第 33 行,接收方需要很长时间才能确认数据。这在第 103 行和第 132 行再次发生。我相信这种延迟是问题的根源。

请注意,我没有修改 SO_SNDBUF 选项和 TCP_NODELAY 选项。

所以我的问题是,为什么我在发送 8192 字节的文件时收到延迟的 ACK,而在使用 8191 字节的块时一切正常?

【问题讨论】:

  • 你能显示一些代码吗?这可能会让我们更好地了解正在发生的事情。另外,您的代码是否在双方都运行?还是只是连接的一侧?
  • 我添加了一些相关部分的伪代码。

标签: windows networking sockets winsock


【解决方案1】:

我想通了!首先是我自己,然后经过更多挖掘,我发现了这个: http://support.microsoft.com/kb/823764

实际发生的情况是,由于 Winsock 分配的发送缓冲区默认情况下(在我的机器上)正好是 8192 字节,当我将这些字节量放入缓冲区(实际上完全填满)时,下一个发送( ) 将给出 WSAEWOULDBLOCK。然后,只有在字节被确认后,我才会收到下一个 FD_WRITE。

但同时,由于延迟 ACK 算法,接收机器没有发送 ACK。这使传输陷入了 200 毫秒的死锁,之后接收机器最终确认数据,然后允许发送函数接收 FD_WRITE。

当然,当我使用 8191 字节时,这一切都不会发生,因为我没有填满整个缓冲区,因此下一个 send() 没有阻塞。这意味着 Winsock 将始终保持发送数据,因此延迟 ACK 算法永远不会在接收端启动(除非是最后一个数据包,如果它是奇数数据包)。

希望这可以帮助其他有同样问题的人。

【讨论】:

    【解决方案2】:

    检查 NIC 和交换机上的“流量控制”设置。如果它打开,则可能是您的问题的原因。

    为了正确解剖,您需要在传输的两端运行wireshark。

    【讨论】:

    • 我在两台机器上都关闭了流控制的情况下再次尝试了它。结果相同。我将尝试在两者上再次使用 Wireshark 进行测试并发布日志。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-03-16
    • 1970-01-01
    • 2018-01-13
    • 1970-01-01
    • 1970-01-01
    • 2016-01-21
    • 1970-01-01
    相关资源
    最近更新 更多