TCP协议是一个可靠的协议。它通过重新发送(retransmission)来实现TCP片段传输的可靠性。简单的说,TCP会不断重复发送TCP片段,直到片段被正确接收。
TCP头部的checksum
接收方(receiver)可以通过校验TCP片段头部中checksum区域来检验TCP片段是否出错。我们已经接触过了IP协议详解的checksum算法。TCP片段的checksum算法与之类似。IP协议的checksum只校验头部,TCP片段头部的checksum会校验包括IP头部、TCP头部和TCP数据在内的整个序列,确保IP地址、端口号和其他相关信息正确。如果TCP片段出错,接收方可以简单的丢弃改TCP片段,也就相当于TCP片段丢失。
TCP片段包裹在一个IP包中传输。IP包可能在网络中丢失。导致IP包丢失的原因可能有很多,比如IP包经过太多的路由器接力,达到hop limit;比如路由器太过拥挤,导致一些IP包被丢弃;再比如路由表(routing table)没有及时更新,导致IP包无法送达目的地。
下面我们要介绍两种重新发送TCP片段的机制:超时重新发送和快速重新发送。
我们之前已经简单介绍过重新发送的机制:当发送方送出一个TCP片段后,将开始计时,等待该TCP片段的ACK回复。如果接收方正确接收到符合次序的片段,接收方会利用ACK片段回复发送方。发送方得到ACK回复后,继续移动窗口,发送接下来的TCP片段。如果直到计时完成,发送方还是没有收到ACK回复,那么发送方推断之前发送的TCP片段丢失,因此重新发送之前的TCP片段。这个计时等待的时间叫做重新发送超时时间(RTO, retransmission timeout)。
RTO:沙漏中沙子的多少
发送方应该在等待多长时间之后重新发送呢?这是重新发送的核心问题。上述过程实际上有往返两个方向:1. 发送片段从发送方到接收方的传输,2. ACK片段从接收方到发送方的传输。整个过程实际耗费的时间称做往返时间(RTT, round trip time)。如果RTT是固定的,比如1秒,那么我们可以让RTO等于RTT。但实际上,RTT的上下浮动很大。比如某个时刻,网络中有许多交通,那么RTT就增加。在RTT浮动的情况下,如果我们设置了过小的RTO,那么TCP会等待很短的时间之后重新发送,而实际上之前发送的片段并没有丢失,只是传输速度比较慢而已,这样,网络中就被重复注入TCP片段,从而浪费网络传输资源。另一方面,如果RTO时间过长,那么当TCP片段已经实际丢失的情况下,发送方不能及时重新发送,会造成网络资源的闲置。所以,RTO必须符合当前网络的使用状况。网络状况越好,RTO应该越短;网络状况越差,RTO应该越长。
RTT: 往返时间
TCP协议通过统计RTT,来决定合理的RTO。发送方可以测量每一次TCP传输的RTT (从发送出数据片段开始,到接收到ACK片段为止),这样的每次测量得到的往返时间,叫做采样RTT(srtt, sampling round trip time)。建立连接之后,每次的srtt作为采样样本,计算平均值(mean)和标准差(standard deviation),并让RTO等于srtt平均值加上四倍的srtt标准差。
RTO = mean + 4 std
(上述算法有多个变种,根据平台不同有所变化)
平均值反映了平均意义上的RTT,平均往返时间越大,RTO越大。另一方面,标准差越大也会影响RTO。标准差代表了RTT样本的离散程度。如果RTT上下剧烈浮动,标准差比较大。RTT浮动大,说明当前网络状况相对不稳定。因此要设置更长的RTO,以应对不稳定的网络状况。
我们刚才介绍了超时重新发送的机制:发送方送出一个TCP片段,然后开始等待并计时,如果RTO时间之后还没有收到ACK回复,发送方则重新发送。TCP协议有可能在计时完成之前启动重新发送,也就是利用快速重新发送(fast-retransmission)。快速发送机制如果被启动,将打断计时器的等待,直接重新发送TCP片段。
由于IP包的传输是无序的,所以接收方有可能先收到后发出的片段,也就是乱序(out-of-order)片段。乱序片段的序号并不等于最近发出的ACK回复号。已接收的文本流和乱序片段之间将出现空洞(hole),也就是等待接收的空位。比如已经接收了正常片段5,6,7,此时又接收乱序片段9。这时片段8依然空缺,片段8的位置就是一个空洞。
补上空洞
TCP协议规定,当接收方收到乱序片段的时候,需要重复发送ACK。比如接收到乱序片段9的时候,接收方需要回复ACK。回复号为8 (7+1)。此后接收方如果继续收到乱序片段(序号不是8的片段),将再次重复发送ACK=8。当发送方收到3个ACK=8的回复时,发送方推断片段8丢失。即使此时片段8的计时器还没有超时,发送方会打断计时,直接重新发送片段8,这就是快速重新发送机制(fast-retransmission)。
快速重新发送机制利用重复的ACK来提示空洞的存在。当重复次数达到阈值时,认为空洞对应的片段在网络中丢失。快速重新发送机制提高了检测丢失片段的效率,往往可以在超时之前探测到丢失片段,并重复发送丢失的片段。
凤凰浴火重生。而TCP协议利用重新发送(retransmission)来实现TCP传输的可靠性。重新发送的基本形式是超时重新发送,根据统计的往返时间来设置超时标准;如果超时,则重新发送TCP片段。另一方面,快速重新发送则通过乱序片段的ACK来更早的推断出片段的丢失。