tcp重复的确认_学习笔记-TCP超时重传

前几章节已经向大家详细的介绍过TCP协议,三次握手,四次挥手,此处不过多赘述,详见个人主页。

超时重传

可靠性中最重要的一个机制是处理数据超时和重传。其原理是在发送某一个数据以后就开启一个计时器,在一定时间内如果没有得到发送的数据报的ACK,那么就重新发送数据,直到发送成功为止。TCP协议要求在发送端每发送一个报文段,就启动一个定时器并等待确认信息;接收端成功接收新数据后返回确认信息。若在定时器超时前数据未能被确认,TCP就认为报文段中的数据已丢失或损坏,需要对报文段中的数据重新组织和重传

传输往返时间

RTT

RTT即传输往返时间(Round Trip Time),简单的说就是某一报文发送至收到这个报文正确接收的确认报文这段时间。由于每个连接都是不同的,所以每个连接的RTT也是不同的。并且在任何时刻连接的RTT都是随机的,无法事先预知。

计算方法

由于在任何时刻连接的RTT都是随机的,无法事先预知。所以RTT是没有一个准确的值,我们只能通过之前的传输特征在计算RTT。TCP通过测量来获得连接当前RTT的一个估计值。为了搜集足够的数据来精确地估算当前的RTT,TCP对每个报文都记录下发送出的时间和收到的确认时间。每一个(发送时间,确认时间)对就可以计算出一个RTT测量值的样本(Sample RTT)。TCP为每一个活动的连接都维护一个当前的RTT估计值。该值是对已经过去的一个时间段内该连接的RTT了两只的加权平均,并作为TCP对连接当前实际的RTT值的一种估计。为了保证它能够比较准确地反应当前的网络状态,每当TCP通过测量获得了个新的RTT样本时,都将对RTT的估计值进行更新。不同的更新算法或参数可能获得不同的特性。通过下面的公式计算得到平滑的RTT估计值(SRTT):

SRTT 

最新的SRTT是根据现存的SRTT和新的样本值RTTs计算出来的。 常在上面的公式中a的取值为:0≤α≤1,RFC推荐的α值为1/8,即0.125。。这种计算方法叫做指数加权移动平均法或则低通过滤器。

值得注意的是,如果α的取值越小,那么SRTT更新相对较平稳;反之α的值越接近于1,则SRTT更新浮动较大。

Karn算法

3e28f5ef768fa67fe573ff864bd2c368.png

如果发生这么一种情况,发送方在时间点1发送了一个M1,假设发送方在超时计时器超时的范围内,即时间点2重传了M1。当发送方在时间点3收到了M1的确认时就懵了,如上图所示,此时发送方不知道这个确认M1到底是对谁的确认,产生了模糊性。

因为新的RTT值要根据报文段发送的时间来计算,如果发送方收到的确认M1是对时间点2中重传M1的确认,则当前RTT的计算必须从时间点2开始计算。如果确认M1是对时间点1的M1的确认,那么当前RTT的计算必须从时间点1开始计算。

对于上面的这种情况,TCP使用了karn算法解决了这种模糊的情况,karn的算法在计算新的RTT时,如果重传了报文,则不会使用新的RTT值,反之,没有重传就更新RTT值。

重传超时时间

RTO

影响超时重传机制协议效率的一个关键参数是重传超时时间(,Retransmission TimeOut)。RTO的值被设置过大过小都会对协议造成不利影响。

过大: RTO设置过大将会使发送端经过较长时间的等待才能发现报文段丢失,降低了连接数据传输的吞吐量。

过小:若RTO过小,发送端尽管可以很快地检测出报文段的丢失,但也可能将一些延迟大的报文段误认为是丢失,造成不必要的重传,浪费了网络资源。

RTO的设定

第一种:固定值

直接把超时时间设成固定值。比如说,我的服务正常请求是30ms,那么我指定100ms。但是这样显然是有问题的,首先我需要知道服务正常请求时间。其次一般情况下客户端与多个服务器交流,这些服务器可能位于天南地北,国内国外,那么时间肯定是不同的。最后,由于网络延迟等不可控因素,也会导致请求时间不同。

所以设置固定值是很不靠谱的,我们应该根据网络延迟,动态调整超时时间,延迟越大,超时时间越长。

第二种:经典方法

通过RTT估计值为基准来设置当前的RTO。如果RTT是可预知的,那么重传机制的设计相对简单得多。但是TCP的底层网络环境是一个完全异构的互联结构。在实现端到端的通信时,不同端点之间传输通路的性能可能存在着巨大的差异,而且同一个TCP连接在不同的时间段上,也会由于不同的网络状态具有不同的传输时延。这种算法的基本要点是TCP监视每个连接的性能(即传输时延),由此每一个TCP连接推算出合适的RTO值,当连接时延性能变化时,TCP也能够相应地自动修改RTO的设定,以适应这种网络的变化。

RTO = min(ubound, max(lbound, (SRTT)β))

β是时延离散因子,推荐值1.3~2.0。

ubound是RTO上边界,

lbound是下边界。

这种计算方法就是经典方法。这种方法缺点就是没法适应大规模的变动(网络不稳定情况)

重传

有了超时就要有重传,但是就算是重传也是有策略的,而不是将数据简单的发送。

013ba41110d1ce66d9acca7ccf07a0f6.png

重传时发送数据的大小

前面曾经提到过,数据在传输的时候不能只使用一个窗口协议,还需要有一个来控制数据的流量,使得数据不会一下子都跑到网路中引起"拥 塞"。也曾经提到过,最初使用指数增长的速度来增加自身的窗口,直到发生超时重传,再进行一次微调。但是没有提到,如何进行微调,拥塞避免算法和 慢启动门限就是为此而生。

所谓的慢启动门限就是说,当超过这个门限的时候,就使用拥塞避免算法,而在门限以内就采用慢启动算法。所以这个标准才叫做门限,通常,拥塞窗口记做cwnd,慢启动门限记做ssthresh。下面来看看拥塞避免和慢启动是怎么一起工作的。

算法概要

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

快速重传和快速恢复算法

  如果我们一连串收到3个或以上的重复ACK,就非常可能是一个报文段丢失了。于是我们就重传丢失的数据报文段,而无需等待超时定时器溢出。这就是快速重传算法。接下来执行的不是慢启动而是拥塞避免算法,这就是快速恢复算法。

  这个算法通常按如下过程实现:

  (1)当收到第3个重复的ACK时,将ssthresh设置为当前拥塞窗口cwnd的一半,重传丢失的报文段,设置cwnd为ssthresh加上3倍的报文段大小。

  (2)每次收到另一个重复的ACK时,cwnd增加1个报文段大小并发送一个1个分组,如果新的cwnd允许发送。

  (3)当下一个确认新数据的ACK到达时,设置cwnd为ssthresh,这个ACK应该是在进行重传后的一个往返时间内对步骤1中重传的确认。另外,这个ACK也应该是对丢失的分组和收到的第一个重复的ACK之间的所有中间报文段的确认。

ICMP差错

  TCP如何处理一个给定的连接返回的ICMP差错。TCP能够遇到的最常见的ICMP差错就是源站抑制、主机不可达和网络不可达。

  (1)一个接收到的源站抑制引起拥塞窗口cwnd被置为1个报文段大小来发起慢启动,但是慢启动门限ssthresh没有变化,所以窗口将打开直到它开放了所有的通路或者发生了拥塞。

  (2)一个接收到的主机不可达或网络不可达实际都被忽略,因为这两个差错都被认为是短暂现象。TCP试图发送引起该差错的数据,尽管最终有可能会超时。

重新分组

  当TCP超时并重传时,它并不一定要重传同样的报文段,相反,TCP允许进行重新分组而发送一个较大的报文段。在协议中这是允许的,因为TCP是使用字节序号而不是报文段序号来进行识别它所要发送的数据和进行确认。

本文的初衷为学习笔记的分享,部分图文来源于网络,如侵,联删。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值