前面也说过,TCP的保序,可用通过ack和seq等数据确定。那么当有包在传输的过程中丢失的话,那么需要一个重传机制去保证可靠性。常见的重传机制:超时重传 快速重传 SACK D-SACK
-
超时重传:
tcp在发送数据的时候,会设定一个定时器。当超过指定的时间后,没有收到对方的ack应答报文或者数据包丢失,就会重发这个数据。这就是超时重传。
image.png
那么超时重传的时候应该设置成多少呢?
这里就是涉及到一个概念:往返时延 RTT。
image.png
而超时重传时间RTO就必须是大于RTT的,但是也不能大太多,丢了半天才重发,性能效率就慢了。
但是RTO计算也没看起来那么简单,因为网络环境是复杂的,RTT可能随时在变,不是一个定值。
linux下需要 TCP 通过采样 RTT 的时间,然后进行加权平均,算出⼀个平滑 RTT 的值,而且这个值还是要
不断变化的,因为网络状况不不断地变化。除了采样 RTT,还要采样 RTT 的波动范围,这样就避免如果 RTT 有⼀个大的波动的话,很难被发现的情况。具体的计算公式很复杂,而且有很多经验值的地方,就不罗列了。
而且当触发到一次超时重传的时候,会将超时RTO设置翻倍,说明现在网络环境不好,需要延长下时间重传,别造成网络拥堵。但是超时时间太长,就会导致传输效率不高的问题,所以说下下一种方法,快速重传。
-
快速重传
超时重传是基于时间触发的,而快速重传是基于数据驱动的。
image.png
如上图,因为seq2一直没有收到,所以ack一直返回seq1的ack2。当连续收到三次ack相同,就会快速重传驱动重传seq,当全部都收到了,就返回ack6。传输结束。不同的tcp实现可能有只重传一个还是重传所有的问题,因为并不知道是不是只缺了seq2,还可能缺3等问题。
-
SACK
SACK是Selective Acknowledgment 选择性确认的缩写。这其实是快速重传的改进方法,也是基于数据驱动的。在tcp头部加一个SACK字段,用来缓存收到的数据标志信息。如图。
image.png
当携带了sack信息,对端就知道具体缺了什么,可以做到只重传部分数据就行。
-
D-SACK
这里的 D是Duplicate,用SACK来告诉发送方有什么数据被重复接收了。这样可以避免重复发送的损耗。
网友评论