前两天看一些关于网络编程的博客,提到了长连接时小数据包发送出现的延时问题。今天打算把这块大概整理梳理一下。
那么最有可能的问题就是没有设置TCP_NODELAY参数。关于这个参数,我们要先了解一下Nagle算法。Nagle算法是拥塞避免相关的算法,在tcp中默认启用,目的是解决大量小数据包造成的带宽浪费。
我们知道,tcp数据包的结构是至少20字节的TCP头+传送内容,当然,还有更前面的20字节的IP头部。显而易见的,当包中传输内容越少,头部占的比重就越大,当出现大量有效报文长度很小(如1字节)的包时,便会造成网络拥塞。于是我们便需要一个解决方案,就是Nagle算法。
Nagle算法之所以可以减少小包的数量,是因为它可以将小包拼接起来发送。
原则上只允许1个未ACK的数据包存在网络,事实上,Nagle算法可以理解为小数据包的停-等协议。
其算法规则如下:
(1)如果包长度达到MSS(最大报文段长度),允许发送;
(2)如果该包含有FIN,允许发送;
(3)设置了TCP_NODELAY选项(相当于直接给禁用了),允许发送;
(4)未设置TCP_CORK选项时,若所有发出去的小数据包(长度小于MSS)均被确认,则允许发送;
(5)上述条件都未满足,但计时器到时(40ms),则立即发送。
什么时候我们需要调用TCP_NODELAY禁用Nagle算法?
当我们的服务对实时性的操作要求比较高的时候,就需要通过调用TCP_NODELAY来降低延迟了。
另外这个算法还可以治愈糊涂窗口综合症,这里的糊涂,一般是指接收端的糊涂(也有特例比如发送端使用telnet协议,一次只产生一个字节)。接收端无脑的通告自己的接收窗口大小,如果这个值很小,那么就很容易产生很多小包,导致网络拥塞。
解决方案:我发我的,不理会对端发送的接受窗口大小就得了呗~
然后TCP_QUICKACK是让服务端尽快的回复ACK。因为有时候为了清理缓冲区,会延时ACK的发送。但是如果服务是实时性要求比较高的,那么我们就不需要这个了,所以需要设置TCP_QUICKACK。
网络编程常见问题