【14】TCP/IP协议族详解-TCP(3)

本博客参考自《TCP/IP详解卷一:协议》

本文主要介绍TCP中的超时重传

1.往返时间RTT的计算

TCP提供可靠的运输层,其中重要的方法之一就是确认从另一端收到的数据。但数据和确认都有可能丢失。TCP通过在发送时设置一个定时器来解决这个问题。如果定时器溢出时还没有收到确认,就重传数据。

TCP超时和重传中最重要的部分是对一个给定连接的往返时间(RTT)的测量。在网络传输的过程中,这个值经常是变化的。RTT的测量必须是在同一报文的发送和确认之间。

较早的时候是通过低通滤波器来更新一个被平滑的RTT估计器来计算超时重传时间RTO(retransmission timeout)。用M表示测量的RTT,R表示被平滑的RTT估计值。

R\leftarrow \alpha R+(1-\alpha ))M

RTO=\beta R

这里的\alpha一般取值0.9,\beta一般取值2。这种方法在RTT的变化范围很大的时候,无法跟上变化,从而引起不必要的重传。所以提出了一种新的方法。除了被平滑的RTT估计器,还需要根据RTT的方差。这种计算方法在往返时间起伏很大的时候可以得到一个较好的响应。

Err=M-A

A\leftarrow A+gErr

D\leftarrow D+h(\left | Err \right |-D)

RTO=A+4D

这里A是被平滑的RTT而D是被平滑的均值偏差。Err是刚得到的测量结果与之前的RTT估计器之差。增量g起平均作用,一般取值0.125。h是偏差的增益,一般取0.25。当RTT增大时,较大的偏差增益将使RTO快速上升。

1.1 Karn算法

在一个分组重传时会产生这样一个问题:假定一个分组被发送。当超时发生时, RTO会进行退避(增长),分组以更长的RTO进行重传,然后收到一个确认。这个确认是针对第一个或第二个分组,难以确认。这就导致重传的二义性。

Karn算法规定,当一个超时和重传发生时,在重传数据的确认最后达到之前,不能更行RTT估计器。

1.2 RTT计算举例

在这个例子中,客户端一共向服务器发送了32678字节的数据,这里只截取了一部分。

从上图中可以看出,RTT的更新只在同一报文的确认到达时才启动。TCP中内置了一个500ms的定时器,没发送一次数据时,这个定时器都会启动。在报文4时,该定时器已经在启动的状态,所以不会对报文段4进行计时,同理7,9报文段。

注意这个定时器同我们理解的定时器不同,它记录的是时钟的滴答,即只要时钟经过一个滴答定时器就加1,记录一个500ms。举例来说,在系统时钟某一滴答后的490ms,你启动了定时器。10ms后系统时钟经历一次滴答,你的定时器就会定时500ms,虽然此时真实的时间只有10ms。

上图显示了实际的RTT同系统时钟的滴答之间的关系,图中虚线表示系统时钟的滴答时刻。可以看出,RTT #1经历的时钟滴答为3,RTT #2经历的时钟滴答为1,RTT #3经历的时钟滴答为2。

下面根据RTT对RTO的值进行估计计算

①初始化A和D分别为0和3

RTO=A+2D=0+2\times 3=6s

因子2D只在初始化的时候出现,后面的计算都会以4D代替。

②同步报文超时重传,RTO指数退避

RTO=A+4D=0+4\times 3=12s

③确认报文2到达

由于估计值A一开始的值为0,所以估计器A需要被初始化。此时RTT为3个时钟滴答,所以M的值为1.5

A=M+0.5=2

D=A/2 = 1

RTO=A+4D = 6s

③确认报文5到达,RTT为1个时钟滴答,M的值为0.5

Err=M-A=0.5-2=-1.5

A=A+gErr=2-0.125\times 1.5=1.8125

D=D+h(\left | Err \right |-D)=1+0.25\times (1.5-1)=1.125

RTO=A+4D=1.8125+4\times 1.125=6.3125

④报文段10到达,RTT为2个时钟滴答,M的值为1

Err=M-A=1-1.8125=-0.8125

A=A+gErr=1.8125-0.125\times 0.8125=1.37109375

D=D+h(\left | Err \right |-D)=1.125+0.25\times (0.8125-1.125)=1.046875

RTO=A+4D=1.37109375+4\times 1.046875=5.55859375

下图是测量的RTT和RTO的曲线

上表是确认报文2到达开始计算的。

2.拥塞避免算法

网络通信有时会达到中间路由器的极限,分组会丢失。拥塞避免是处理这种丢失分组的方法。该方法假设,分组丢失是由源主机和目的主机之间的某处网络故障造成的。有两种情况表示分组丢失:发生超时和接收到重复确认。

当拥塞发生时,为了降低分组进入网络的传输速率,需要调用慢启动算法来实现。拥塞避免和慢启动算法需要对每个连接维持两个变量一个拥塞窗口cwnd和一个慢启动门限ssthresh。这样得到的算法的工作过程如下:

1) 对一个给定的连接,初始化cwnd为1个报文段,ssthresh为6 5 5 3 5个字节。
2) TCP输出例程的输出不能超过cwnd和接收方通告窗口的大小。拥塞避免是发送方使用的流量控制,而通告窗口则是接收方进行的流量控制。前者是发送方感受到的网络拥塞的估计,而后者则与接收方在该连接上的可用缓存大小有关。
3) 当拥塞发生时(超时或收到重复确认),ssthresh被设置为当前窗口大小的一半(cwnd)和接收方通告窗口大小的最小值,但最少为 2个报文段)。此外,如果是超时引起了拥塞,则cwnd被设置为1个报文段(这就是慢启动)。
4) 当新的数据被对方确认时,就增加cwnd,但增加的方法依赖于我们是否正在进行慢启动或拥塞避免。如果cwnd小于或等于ssthresh,则正在进行慢启动,否则正在进行拥塞避免。慢启动一直持续到我们回到当拥塞发生时所处位置的半时候才停止(因为记录了在步骤 2中给我们制造麻烦的窗口大小的一半),然后转为执行拥塞避免。

拥塞避免算法要求每次收到一个确认时将cwnd增加为1/cwnd。这样就保证理想情况下每个往返时间增加一个窗口大小。这是一种线性增长。下图展示了慢启动和拥塞避免算法的工作流程。

cwnd=32时发送拥塞,接着ssthresh=32/2=16,cwnd=1,这时执行慢启动算法。当cwnd=16时,慢启动算法失效,每个RTT内只增加一个cwnd

3.快速重传和快速恢复算法

TCP的连接中,当收到3个以上的重复ACK,就认为是报文段的丢失。接下来就会重传数据报文段,无需等待超时定时器溢出。这就是快速重传算法。快速重传算法首先执行拥塞避免算法,而不是慢启动,这就是说cwnd不会变为1。算法的具体流程如下:

1) 当收到第3个重复的ACK时,将ssthresh设置为当前拥塞窗口cwnd的一半。重传丢失的报文段。设置cwndssthresh加上3倍的报文段大小。
2) 每次收到另一个重复的ACK时,cwnd增加1个报文段大小并发送 1个分组(如果新的cwnd允许发送)。
3) 当下一个确认新数据的A C K到达时,设置cwndssthresh(在第1步中设置的值)。这个ACK应该是在进行重传后的一个往返时间内对步骤 1中重传的确认。另外,这个ACK也应该是对丢失的分组和收到的第 1个重复的ACK之间的所有中间报文段的确认。这一步采用的是拥塞避免,因为当分组丢失时将当前的速率减半。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值