奇怪的send()问题(使用Wireshark日志)

时间:2010-04-21 21:37:35

标签: windows networking sockets winsock

我对这个问题有另一个问题,但我没有正确地问,所以我再来一次!

我通过发送文件发送文件。现在,我正在玩那个块大小的不同数字,看看哪个大小最有效。

在localhost上测试时,任何块大小似乎都可以正常工作。但是当我通过网络测试它时,似乎最大块大小是8191字节。如果我尝试更高的任何东西,那么转移就变得极其痛苦,缓慢。

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

8191:http://pastebin.com/E7jFFY4p

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

请注意,在第7行的8192日志中,接收器如何花费很长时间来确认数据。这在第103行和第132行再次发生。我认为这种延迟是问题的根源。

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

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

2 个答案:

答案 0 :(得分:1)

我明白了!首先由我自己,然后经过一些挖掘后,我发现了这个: http://support.microsoft.com/kb/823764

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

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

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

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

答案 1 :(得分:0)

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

为了正确解剖,你需要在转移的两端运行wireshark。