TCP/IP协议--TCP的超时和重传

  TCP是可靠传输。可靠之一体如今收到数据后,返回去一个确认。可是不能彻底避免的是,数据和确认均可能丢失。解决这个办法就是,提供一个发送的重传定时器:若是定时器溢出时还没收到确认,它就重传这个报文段。算法

想法是完美的,关键之处在于超时和重传的策略,即怎么决定超时间隔和如何肯定重传的频率。缓存

书中举了一个简单的超时重传例子:网络

如图:tcp

好比A往B传,传了一部分数据后,把B的网线拔了(前边讲过,若是不传数据的话,双方无法知道这个链接已经断了)。而后开始A再给B发数据,此时tcpdump出来发现,连续重传了一个报文段:时间间隔分别是,1.013s, 3, 6, 12, 24 和多个64s...最后发了个复位报文段表示我放弃了。。(从第一次开始发这个报文段,到最后发一个复位段的时间差大约是9分钟,这个9分钟通常在TCP实现中是不变的)。性能

往返时间测量:
TCP的超时时间很大程度上是依赖报文段的往返时间。所以测量往返时间显得尤其重要。
由于链路上的网络流量或者路由器等的存在,往返时间通常不会是一成不变的,可能会常常发生变化。
最初的TCP规范这样协议:RTT(Round-Trip Time)表示往返时间,用M表示测量到的RTT。
更新过的RTT = 0.9*RTT + 0.1*M 表示,我估计新的往返时间将是,0.9倍的以前的RTT + 0.1倍的新测量的RTT。(0.9叫平滑因子)
获得了新的估计RTT,推荐的重传超时时间RTO(Retransmission TimeOut)的值应该设置为
RTO = RTT*b (这里的b是一个推荐值为2的时延离散因子)。超时时间就是大约2倍的往返时间。spa

以上这个计算超时时间的方法存在缺陷,[Jacobson 1988] 做出了详细分析,当RTT变化范围比较大的时候,这个方法显得力不从心了,可能会引发没必要要的重传。这样当网络负载比较高的时候,再重传会火上浇油...
     这就又有了新的方法计算重传超时时间:
前边说到若是RTT变化范围较大时,容易发生没必要要重传。学过数学的都会知道,方差能够体现出波动大小。这个方法就是用到了方差来均衡下。
这里有个公式用来计算RTO,懂的原理就行了,这个计算RTO的公式依赖于估计的RTT和均值误差(逼近与标准差),而最初的方法则使用了被平滑的RTT的一个倍数(b=2)。这块知道是这么个事就好~blog

 

往返时间RTT的测量:
如图:排序

左边的时间轴上有三个括号,它们代表为进行RTT计算对哪些个报文段进行了计时,并非全部的报文段都被计时。在发送一个报文段时,若是给定链接的重传定时器已经被使用,则该报文段不被计时。如图报文段4或者报文段7都没有参与计时。
对每一个链接而言,除了这个滴答计数器,报文段中数据的起始序号也被记录下来。当收到一个包含这个序号的确认后,该定时器就被关闭。若是ACK到达时数据没有被重传,则被平滑的RTT和被平滑的均值误差将基于这个新测量进行更新。进程

在每次调用500 ms的TCP的定时器例程时,就增长一个计数器来完成计时。这意味着,若是一个报文段的确认在它发送550 ms后到达,则该报文段的往返时间RTT将是1个滴答(即500 ms)或是2个滴答(即1000 ms)。
如图RTT测量和时钟滴答:ip

 

  -拥塞举例:
主机slip老是通告窗口大小为4096,而主机vangogh则通告窗口为8192。
如图:


报文段45丢失了,报文段58是正常接收43的报文段给出的确认,而后接着接收主机连续发了8个ack 6657。能够看出是重发第三次(除了正常确认的中第3个)时,发送主机重传发送了63报文段。
这收到第三个ack才重传也是算法中要求的,当收到第3个时,就假定一个报文段已经丢失并重传自那个序号起的一个报文段。这就是Jacobson的快速重传算法
值得注意的是,在重传后(报文段63),发送方继续正常的数据传输(报文段6七、69和71)。TCP不须要等待对方确认重传。

这里再分析一下接收端是怎么处理的: 当按序收到正常数据(报文段43)后,接收TCP将255个字节的数据交给用户进程。但下一个收到的报文段(报文段46)是失序的(数据的开始序号 6913 并非下一个指望的序号 6657)。TCP保存256字节的数据,并返回一个已成功接收数据的最大序号加1(6657)的ACK。被vangogh接收到的后面7个报文段(48, 50, 52, 54, 55, 57和59)也是失序的,接收方TCP保存这些数据并产生重复ACK(TCP实现无法告诉对方,我就缺某某个报文段,它只能告诉发送方个人确认序号一直是这个)。
当缺乏的报文段(报文段 63)到达时,接收方TCP在其接收缓存中组合好第6657~8960字节的数据,并将这2304字节的数据交给用户进程。全部这些数据在报文段72中进行确认。
值得注意的是,此时该ACK通告窗口大小为5888(8192-2304,原来的通告窗口大小是8192),这是由于用户进程此时尚未读取出这些缓存中的字节。

 

  -拥塞避免:
该算法假定因为分组受到损坏引发的丢失是很是少的(远小于1%),所以分组丢失就意味着在源主机和目的主机之间的某处网络上发生了拥塞。
有两种分组丢失的指示:发生超时和接收到重复的确认(若是使用超时做为拥塞指示,则须要使用一个好的RTT算法)。
前边讲过慢启动,拥塞避免算法和慢启动算法是两个目的不一样、独立的算法。可是当拥塞发生时,咱们但愿下降分组进入网络的传输速率,因而能够调用慢启动来做到这一点。在实际中这两个算法一般在一块儿实现。

  -快速重传和快速恢复算法:
在前边拥塞举例时,观察到第三个ack过来,发送端才进行重传。这是由于:因为咱们不知道一个重复的ACK是由一个丢失的报文段引发的,仍是因为仅仅出现了几个报文段的从新排序,所以咱们等待少许重复的ACK到来。假如这只是一些报文段的从新排序,则在从新排序的报文段被处理并产生一个新的ACK以前,只可能产生1 ~ 2个重复的ACK。 若是一连串收到3个或3个以上的重复ACK,就很是多是一个报文段丢失了。因而咱们就重传丢失的数据报文段,而无需等待超时定时器溢出。这就是快速重传算法。
接下来收到重传的ACK之前,发送了3个新的数据的报文段(报文段67,69和71)。执行的不是慢启动算法而是拥塞避免算法。这就是快速恢复算法。在这种状况下没有执行慢启动的缘由是因为收到重复的ACK不只仅告诉咱们一个分组丢失了,而是在收发两端之间仍然有流动的数据(因为接收方只有在收到另外一个报文段时才会产生重复的ACK,而该报文段已经离开了网络并进入了接收方的缓存),所以咱们不想执行慢启动来忽然减小数据流。

 

从新分组:
当TCP超时并重传时,它不必定要重传一样的报文段。而是TCP容许进行从新分组而发送一个较大的报文段,这将有助于提升性能(固然,这个较大的报文段不可以超过接收方声明的MSS)。
如图:

第3个发送前,断开网线。开始发送3,此时发生了重传,在放弃链接前,又键入了几个字节。而后插上网线,发现第8行,是把前边两次的分组组装成了一个分组发过去的。

 

TCP的超时重传...end

-

相关文章
相关标签/搜索