Delayed ACK
Delayed ACK是TCP 的一种流控手段。如果有响应数据发送时,ACK会随响应数据一起发送给对方;如果没有响应数据,ACK的发送就会有延迟,以等待看是否有响应数据一起发送。
Nagle算法
Nagle算法是通过减少网络连接中<MSS的数据包的数量,从而防止网络拥塞的控制手段。任意时刻中最多只能有一个未被确认的小包(尺寸<MSS的数据包)。简单来说,当发送方要发出不满MSS的数据包时,需要前面发出的数据包都得到ACK确认。而接收方因为Delayed ACK的原因延迟了ACK的回应,导致发送方和接收方都在等待,造成了我们所说的ACK延迟。
Delayed ACK+Nagle算法
假设一端发送数据并等待另一端应答,协议上分为头部和数据,发送的时候不幸地选择了write-write,然后再read,
也就是先发送头部,再发送数据,最后等待应答。发送端的伪代码是这样
write(head);
write(body);
read(response);
接收端的处理代码类似这样:
read(request);
process(request);
write(response);
这里假设head和body都比较小,当默认启用nagle算法,并且是第一次发送的时候,根据nagle算法,第一个段head可以立即发送,因为没有等待确认的段;接收端收到head,但是包不完整,继续等待body达到并延迟ACK;发送端继续写入body,这时候nagle算法起作用了,因为head还没有被ACK,所以body要延迟发送。这就造成了发送端和接收端都在等待对方发送数据的现象,发送端等待接收端ACK head以便继续发送body,而接收端在等待发送方发送body并延迟ACK,悲剧的无以言语。这种时候只有等待一端超时并发送数据才能继续往下走。
只要避免write-write-read形式的调用就可以避免延迟现象,利用writev做聚集写或者将head和body一起写,然后再read,变成write-read-write-read的形式来调用,就无需禁用nagle算法也可以做到不延迟。
双方不会无限制等待下去,最多不超过500ms,一般情况下系统内核启动的定时器默认200ms的延迟。从0到200循环计时,每隔200ms检查是否有ACK需要发送,因此ACK延迟可能是200ms内任意一个数值。
Nagle算法只适用于特定的场景。有一种说法认为Nagle算法引入了不必要的延迟
同时看下以前的文章 delay ack nagle相关笔记 nagle delay相关文章
- #define TCP_NODELAY 1 /* Turn off Nagle's algorithm. */
- #define TCP_CORK 3 /* Never send partially complete segments */
http代理服务器(3-4-7层代理)-网络事件库公共组件、内核kernel驱动 摄像头驱动 tcpip网络协议栈、netfilter、bridge 好像看过!!!! 但行好事 莫问前程 --身高体重180的胖子