1 TCP超时与重传
1.1 引言
TCP提供可靠的运输层.他使用的方法之一就是确认从另一端收到的数据.但数据和确认都有可能会丢失.TCP通过在发送时设置一个定时器来解决这种问题.如果当定时器溢出时还没收到确认,他就重传该数据.对于任何实现而言,关键之处就在于超时和重传的策略,即怎样决定超时间隔和如何确定重传的频率.
TCP管理4个不同的定时器
(1) 重传定时器使用于当希望收到另一端的确认
(2) 坚持定时器使窗口大小信息保持不断流动,即使另一端关闭了其接收窗口
(3) 保活定时器可检测到一个空闲连接的另一端何时崩溃或重启
指数退避:书中检查连续重传之间不同的时间差,它们取整后分别是1、3、6、12、24、48和多个64秒,其中第一次发送后设置的超时时间设置为1.5秒。(2的N次方*1.5秒)
1.2 往返时间测量
计时器的使用
- 一个连接中,有且仅有一个测量定时器被使用。也就是说,如果TCP连续发出3组数据,只有一组数据会被测量。
- ACK数据报不会被测量,原因很简单,没有ACK的ACK回应可以供结束定时器测量。
超时时间的计算是超时的核心部分,TCP要求这个算法能大致估计出当前的网络状况,虽然这确实很困难。要求精确的原因有两个:(1)定时太久会造成网络利用率不高。(2)定时太短会造成多次重传,使得网络阻塞。所以,书中给出了一套经验公式,和其他的保证计时器准确的措施。
RTT(往返时间):指发送端发送TCP报文段开始到接收对方的确定所用的时间.
TCP超时与重传中最重要的部分就是对一个给定连接的往返时间(RTT)的测量.由于路由器和网络流量均会变化,因此我们认为这个时间可能会经常发生变化,TCP应该跟踪这些变化并相应的改变其超时时间.
RTO(重传超时时间):发送端发送TCP报文段后,在RTO时间内没有收到对方确定,即重传该报文段.
最早的TCP曾经用了一个非常简单的公式来估计当前网络的状况,如下:
R <- αR + (1 - α)M
RTO= Rβ
这里的α是一个推荐值为0.9的平滑银子因子。每次进行新测量的时候,这个平滑的RTT将的到更新。每个新估计的90%来自前一个估计,而10%则取自新的测量。
但是在RTT变化范围很大时,使用这个方法无法跟上这种变化,从而引起不必要的重传。于是就有了基于均值和方差的改良公式。
Err=M-A
A<-A+gErr
D<-D+h(|Err|-D)
RTO=A+4D
A是被平滑的RTT(均值的估计器)
D是被平滑的均值偏差
Err是刚得到的测量结果与当前RTT估计器之差。
A与D均被用于计算下一个重传时间(RTO )
增量g起平均作用,取为1/8(0.125)
偏差的增益是h,取值0.25
当RTT变化时,较大的偏差增益使RTO快速上升
karn算法(重传多义性)
假如发送一个分组,当发生超时,RTO指数退避,重传该分组,然后收到ACK。此时但并不能确定这个ACK是针对第一个分组还是重传分组,这就是重传多义性问题。
karn算法针对这个问题
(1) 对于超时重传的数据报的确认,不更新RTT。
(2) 要注意的是:重传的情况下,RTO不用上面的公式计算,而采用一种叫做“指数退避”的方式。RTO指数退避,下一次传送就使用这个RTO值。
(3) 重传数据确认之后,再次发送的数据如果正常被确定,恢复Jacobson 1988公式,更新RTO和RTT。
1.3 拥塞避免算法
拥塞避免算法是一种处理丢失分组的方法。该算法假定由于分组收到损坏引起的丢失是非常少的(远小于1%),因此分组丢失就意味着在源主机和目的主机之间的某处网络上发生了拥塞。
有两种分组丢失的指示:
(1) 发生超时
(2) 接收重复的确认
拥塞避免算法和慢启动算法是两个目的不同,独立的算法。但是当拥塞发生时,我们希望降低分组进入网络的传输速率,于是可以调用慢启动来做到这一点。在实际中这两个算法通常在一起实现。
拥塞避免算法和慢启动算法需要对每个连接维持两个变量:
(1) 一个拥塞窗口cwnd
(2) 一个慢启动门限ssthresh
算法工作过程
(1) 对一个给定的连接,初始化cwnd为一个报文段,ssthresh为65535个字节
(2) TCP输出例程的输出不能超过cwnd和接收方通告窗口的大小。拥塞避免是发送方使用的流量控制,而通告窗口则是接收方进行的流量控制。前者是发送方感受到的网络拥塞的估计,而后者则与接收方在该连接上的可用缓存大小有关。
(3) 当拥塞发生时(超时或收到重复确认),ssthresh被设置为当前窗口大小的一半(cwnd和接收方通告窗口大小的最小值,但最少为2个报文段)。此外,如果是超时引起了拥塞,则cwnd被置为1个报文段(这就是慢启动)
(4) 当新的数据被对方确认时,就增加cwnd,但增加的方法依赖于我们是否正在进行慢启动或拥塞避免。如果cwnd小于或等于ssthresh,则正在进行慢启动,否则正在进行拥塞避免。慢启动一直持续到我们回到当拥塞发生时所处位置一半的时候才停止(因为我们记录了在步骤2中给我们制造麻烦的窗口大小的一半),然后转为执行拥塞避免。
cwnd增加方式:
慢启动初始cwnd为1,每收到一个确定就加1.成指数增长.
拥塞避免算法在每个RTT内增加 1/cwnd 个报文,成线性增长.
慢启动根据收到的ACK次数增加cwnd,而拥塞避免算法在一个RTT不管收有多少ACK也只增加一次.
1.4 快速重传与快速恢复算法
如果一连串收到3个或3个以上的重复ACK,就非常可能是一个报文段丢失了。于是我们就重传丢失的数据报文段,而无需等待超时定时器溢出。这就是快速重传算法。接下来执行的不是慢启动算法而是拥塞避免算法。这就是快速恢复算法。
算法过程:
(1) 当收到第3个重复的ACK,将ssthresh设置为当前拥塞窗口cwnd的一半。重传丢失的报文段。设置cwnd为ssthresh加上3倍的报文段大小。
(2) 每次收到另一个重复的ACK时,cwnd增加一个报文段大小并发送一个分组(如果新的cwnd允许发送)
(3) 当下一个确认新数据的ACK到达时,设置cwnd为sshresh(在第一步中设置的值)。这个ACK应该是在进行重传后的一个往返时间内对步骤1中重传的确认。另外,这个ACK也应该是对丢失的分组和收到的第1个重复的ACK之间的所有中间报文段的确认。这一步采用的是拥塞避免,因为当分组丢失时我们将当前的速率减半。
1.5 icmp(internet控制报文协议)差错
TCP能够遇到的最常见的ICMP差错就是源站抑制,主机不可达和网络不可达
(1)源站抑制的ICMP将拥塞窗口cwnd置为1个报文段,并发起慢启动,慢启动门限ssthresh不变,窗口将打开直至开放了所有的通路(受窗口大小和往返时间的限制)或者发生了拥塞。
(2)主机不可达或网络不可达的ICMP将被忽略,因为这两上差错都被认为是短暂现象。
1.6 重新分组
当TCP超时并重传时,他不一定要重传同样的报文段。相反,TCP允许进行重新分组而发生一个较大的报文段,这将有助于提高性能(当然,这个较大的报文段不能超过接收方声明的MSS.