TCP_NODELAY
在写游戏服务器的时候,连接建立后通常会设置一个选项:TCP_NODELAY,该选项会禁用Nagle算法。
Nagle算法的作用是减少小包的数量,它是如何做到的呢(注意我是抄书的,如果不对欢迎指正)?
- 什么是小包:小于 MSS(一个TCP段在网络上传输的最大尺寸) 的都可以定义为小包。
- 如果前一个TCP段发送出去后,还没有收到对端的ACK包,那么接下来的发送数据会先累积起来不发。
- 等到对端返回ACK,或者数据累积已快达到MSS,才会发送出去。
拿telnet的字符回响来示例,在默认情况下(Nagle算法开启),假如敲键盘的速度是250ms一下,网络RTT(一个包到达目标,然后目标回应的总时间)是600ms:
客户端的感受就是有延迟,字符一批一批的显示出来。如果禁用Nagle算法,效果是这样的:
也能感受到延迟(因为网络本来就慢),但字符的显示是均匀的,一个个出来。
Nagle算法经常还和对端的延迟ACK算法碰到一起,TCP端收到包后,不马上ACK回去,而是延迟一点点时间,如果这段时间有包要发送回去,则上一个ACK刚好合并在一起发。从这可看出Nagle算法和延迟ACK算法的目的都是一样的:减少TCP段的传输数量。
但在网络游戏这种实时通信中,这种减少包的做法,如果网络较差的时候,可能会引起比较大的波动,比如玩家正在PK,发了技能没有很快的反馈,过一会儿很多技能效果一起回来,这个体验是比较差的。
使用TCP_NODELAY可以禁用Nagle算法,坏处就是小包比较多,对网络交通会有负担,拿个不一定恰当的比喻:
开了Nagle算法相当于大家尽量做公交车,这样路上的小车少了,交通会通顺一些,但是要等公交车;如果大家都开车,对交通的负载会加大。