前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >TCP TCP_NODELAY选项与神秘的40ms延迟

TCP TCP_NODELAY选项与神秘的40ms延迟

原创
作者头像
LuceneReader
修改2020-06-22 10:29:26
3.6K0
修改2020-06-22 10:29:26
举报

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

的伪代码。

代码语言:javascript
复制
 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 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档