我发现它可以在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毫秒,依此类推。
这是错的吗?
答案 0 :(得分:4)
通常,TCP将数据保留在发送缓冲区中,直到被对等方确认为止。在您的情况下,没有发送缓冲区(因为SO_SNDBUF = 0)。因此TCP阻止发送方保留数据以进行可能的重传。对等体的TCP堆栈使用“Delayed ack”例程,并在200ms延迟后发送确认(或直到收到数据的2个数据包而没有执行)。
因此,发件人将被阻止,直到所有数据都被对等方确认。 如果网络的RTT很长,或者丢包发生,则可能需要200ms以上。
答案 1 :(得分:3)
延迟的全部意义在于查看是否有更多数据可以添加到同一消息中。第一条消息不应该成为这条规则的例外。
答案 2 :(得分:3)
Nagle算法背后的想法是优化这样的案例:
如果没有Nagle算法,它将导致3个独立的数据包,每个数据包都有几个字节的标头,只有1个字节的有用负载。这意味着很多开销。
使用Nagle算法,相同的send()调用序列将导致只有1个包含一些头字节和3个字节的有效负载,从而减少了开销大小。但是,数据包将在您第一次通话后200毫秒发送。
Nagle算法的想法是等待你发送一小部分数据,期望你可能想要发送更多。由于系统不知道您将来发送任何内容的计划,它会等待一段合理的时间(200毫秒),如果不再发送任何内容,它会发送实际数据包,不会使延迟太大。
如果您在不等待回复的情况下以小块发送数据(例如,逐行发送文本文件),该算法将对您的程序有益。这将大大减少通过网络发送的数据包数量和相关的开销。
如果您的程序对响应时间敏感且不需要此优化,则可以通过使用TCP_NODELAY参数调用setsockopt()来安全地禁用它,甚至可以考虑使用UDP而不是TCP。
答案 3 :(得分:0)
老实说,我不记得第一条消息也被延迟的行为。我使用WinSock,数据运行顺利。他们可以通过这种方式实现它,因为这不违反任何标准。这就是答案。