TCP_NODELAY是用来禁用Nagle’s Algorithm的。Nagle’s Algorithm设计的目的是提高网络带宽利用率,其做法是合并小的TCP包为一个大的TCP包,避免过多的小的TCP的报文的TCP头部浪费网络带宽,操作系统默认是开启这个算法的,如果开启这个算法,TCP/IP协议栈会累积数据,直到以下条件满足,才会将数据真正发送出去。
1. 累积的数据量达到最大的TCP Segment Size
2. 收到一个ACK
TCP Delayed ACK 也是基于同样的目的而设计出来的,他的作用就是延迟ACK包的发送,使得协议栈可以合并多个ACK,提高网络利用率。
如果TCP连接的一端开启Nagle’s Algorithm,而另一端开启TCP Delayed Ack,而发送的数据包比较小,则会出现下面的情况:发送端在等待接收端收到的上一个数据包的ACK才会发送当前的数据包,而接收端正好延迟了这个ACK的发送,那么这个正要被发送的数据包同样被延迟,TCP Delayed ACK是有超时机制的,而默认的超时时间是40ms。
现代的TCP/IP协议栈默认都是开启这个功能的,Write-Write-Read 模式会出现上面的问题。下面我们列出Nagle’s Algorithm
的伪代码。
if there is new data to send
if the window size >= MSS and available data is >= MSS
send complete MSS segment now
else
if there is unconfirmed data still in the pipe
enqueue data in the buffer until an acknowledge is received
else
send data immediately
end if
end if
end if
当发送的数据比MSS小的时候,还要再判断是否还有未确认的数据,只有管道中还有未确认的数据包的时候,才会进入到缓冲区,等待ACK。所以发送端发送的第一个write是不会被缓存起来的,而是立刻发送出去,这个时候,接收端接收到对应的数据,不会立刻发送ACK,此时发送端发送第二个write,因为队列中还有未ACK的数据包,此时这个数据包会被缓存起来,发送端在等待接收端的ACK,而接收端在Delay这个ACK,所以都在等待,直到接收端Delayed Ack超时,此时Ack被发送回去,发送端缓存的这个write才会真正的发送出去。而write-read-write-read是不会出现问题的。
write->write->read:第一个write立刻发送出去,但是数据包比较小,接收端不会立即发送ACK,第二个write比较小,第二个write只有等到第一个write的ack后才会发送出去,所以才导致延迟40ms才会将write发送出去。
write->read->write->read:第一个write立刻发送出去,但是数据包比较小,接收端不会立刻发送ACK,不过此时发送端为read,等40ms再收到ack也没有关系,不会导致第二个write延迟发送。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。