Winsock 200毫秒延迟问题

Winsock 200ms delay issue

本文关键字:问题 延迟 200毫 Winsock      更新时间:2023-10-16

我发现WinSock发送呼叫可能会延迟200ms

来自MSDN:http://support.microsoft.com/kb/214397/en

Nagle算法:http://en.wikipedia.org/wiki/Nagle算法

问题摘要

如果重复发送带有SO_ SNDBUF"0"选项的小消息(<MTU),发送功能块200ms。

我的问题:为什么第一次发送消息延迟200ms?

因为TCP在第一次发送呼叫之前是空闲的,所以我认为必须立即发送第一条消息。

但测试结果并不理想。

第一条消息也延迟了200ms,为什么?

谢谢你的回答。

添加一些详细信息

Naggle算法适用于以下小消息:

1. if wire is idle, send it immediately.
2. if formal message's ACK is not received, wait until ACK & send
3. Window's TCP ack delay mechanism send ack after 200ms.

所以,我的期望是第一条消息立即发送,第二条消息等待第一条消息的确认200ms,以此类推

这错了吗?

通常TCP会将数据保存在发送缓冲区中,直到对等方对其进行确认。在您的情况下,没有发送缓冲区(因为SO_SNDBUF=0)。因此,TCP阻止发送方保留数据以备可能的重传。对等端的TCP堆栈使用"延迟确认"例程,并在200ms延迟后发送确认(或直到接收到2个带有数据的数据包而没有确认)。

因此,在对等方确认所有数据之前,发送方将被阻止。如果网络的RTT很长,或者发生数据包丢失,则可能需要超过200ms的时间。

延迟的全部目的是查看是否有更多数据可以添加到同一消息中。没有理由认为第一条消息应该是该规则的例外。

Nagle算法背后的想法是优化这样的情况:

  1. 在send()调用中发送1字节的数据
  2. 1毫秒后,用1字节的数据再次调用send()
  3. 1毫秒后,您再次调用send()

如果没有Nagle算法,它将导致3个单独的分组,每个分组具有几个字节的报头和只有1个字节的有用有效载荷。这将意味着大量的开销。

使用Nagle算法,相同的send()调用序列将只产生一个具有一些报头字节和3个有效载荷字节的数据包,从而减少了开销大小。但是,数据包将在您第一次通话后200毫秒发送。

Nagle算法的想法是在发送一小块数据后等待,预计您可能会想要发送更多数据。由于系统不知道你未来发送任何东西的计划,它会等待一段合理的时间(200毫秒),如果没有发送任何信息,它会发送实际的数据包,以免延迟太大。

如果你在不等待回复的情况下以小块的形式发送数据(例如逐行发送文本文件),该算法将对你的程序有益。这将大大减少通过网络发送的数据包数量和相关开销。

如果您的程序对响应时间敏感,并且不需要此优化,则可以通过使用TCP_NODELAY参数调用setsockopt()来安全地禁用它,甚至可以考虑使用UDP而不是TCP。

老实说,我不记得第一条消息也被延迟的行为。我使用了WinSock,数据运行得很顺利。他们可以用这种方式实现它,因为这并不违反任何标准。这就是答案。