golang tcp_nodelay延迟参数的趣事

前言:

tcp_nodelay是tcp协议里nagle算法和delay ack的控制开关,nagle是什么? 简单说通过缓冲区合并包来减少包的数量,来提高网络的利用率。

该文章后续仍在不断的更新修改中, 请移步到原文地址 http://xiaorui.cc/?p=6311

nagle算法的基本定义是任意时刻,最多只能有一个未被确认的小段。所谓“小段”,指的是小于MSS尺寸的数据块,所谓“未被确认”,是指一个数据块发送出去后,没有收到对方发送的ACK确认该数据已收到。

在开启nagle算法下的流程,数据包会先放到socket写缓冲区,只有当缓冲区的数据大于mss,上一个ack到达,或者 触发定时器才会发送。 下面是wiki里找到的关于nagle的伪代码:

tcp的delay ack又是什么? 当server收到一个包准备返回一个ack,但因为一个tcp最少占用40个字节,为了提高带宽利用率,可以跟数据一起返回,或者等其他ack返回。如果没人跟他一起返回,那么会依赖定时器发送。

到这里可以得知,nagle和delayed ack是牺牲网络的及时性来提高网络的利用率,但现在市面上的网络框架默认多是开启nodelay的。但我这边想测测在nodelay=false的情况下,移动端是个什么情况。

Golang tcp_NoDelay问题

golang在net库默认是开启nodelay=true的,就是关闭nagle和时延ack算法。nagle缺点就是高延迟,但他所谓的优点是提高网络利用率。但根据我的大量测试,关闭nodelay跟开启nodelay的网络质量是一样的。很奇怪。。。

写了个demo进行测试,抓包发现数据并没有合并发送。

用strace追看下client端的系统调用,setsockopt是用来操作tcp属性的系统调用,我们会发现他调用了两遍,第一遍是go std net默认会开启nodelay,第二遍是我们手动触发关闭nodelay。

那么可能是server端代码没有配置关闭nodelay引起的问题? net.Conn本身没有提供tcp_nodelay的方法,需要转换到net.TCPConn来操作。

但依旧有问题,还是没看延迟的效果…. 下面是server端的setsockopt系统调用。

总结:

估计是由于操作系统的原因,导致测试不到tcp延迟的效果。懒得测试了。


大家觉得文章对你有些作用! 如果想赏钱,可以用微信扫描下面的二维码,感谢!
另外再次标注博客原地址  xiaorui.cc