Winsock 200ms延迟问题

时间:2012-07-12 08:25:40

标签: c++ winsock

我发现它可以在WinSock发送呼叫上延迟200ms

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

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

问题摘要

如果重复发送带有SO_SNDBUF“0”选项的小msg(< 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.

所以,我的期望是第一个消息立即发送,第二个消息等待第一个消息的确认200毫秒,依此类推。

这是错的吗?

4 个答案:

答案 0 :(得分:4)

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

因此,发件人将被阻止,直到所有数据都被对等方确认。 如果网络的RTT很长,或者丢包发生,则可能需要200ms以上。

答案 1 :(得分:3)

延迟的全部意义在于查看是否有更多数据可以添加到同一消息中。第一条消息不应该成为这条规则的例外。

答案 2 :(得分:3)

Nagle算法背后的想法是优化这样的案例:

  1. 您在send()调用中发送1个字节的数据
  2. 1毫秒后,再次使用1字节数据
  3. 调用send()
  4. 再过1毫秒后,再次拨打send()
  5. 如果没有Nagle算法,它将导致3个独立的数据包,每个数据包都有几个字节的标头,只有1个字节的有用负载。这意味着很多开销。

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

    Nagle算法的想法是等待你发送一小部分数据,期望你可能想要发送更多。由于系统不知道您将来发送任何内容的计划,它会等待一段合理的时间(200毫秒),如果不再发送任何内容,它会发送实际数据包,不会使延迟太大。

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

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

答案 3 :(得分:0)

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