tcp/ip学习笔记--第21章 Timeout and Retransmission

来源:互联网 发布:c语言运行根号怎么表示 编辑:程序博客网 时间:2024/06/06 18:54

超时重传这个词不知道听过多少次了,现在终于有机会来学习一波其背后的工作原理了,爽.....

学的过程中才发现,有的概念理解起来还是蛮困难的。

简介:

tcp通过接收方对发送的数据进行确认来保证数据传输的可靠性。当数据传送过程中被丢失,就需要进行重传。tcp通过对发送的数据设置定时器,当定时器溢出的时候还没有收到对应的确认就进行传。超时重传非常重要的一部分就是RTT的测量,从而合理的设置超时重传的时间。


简单的超时重传的例子

当tcp连接建立好后,发送数据前,将线路断开,观察重传的时间间隔,发现取整之后的时间间隔如下:

1,3,6,12,24,48,60,60,60...

第一个值其实应该是1.5,原因以前解释过:第一个时钟周期是随机的0-500ms。可以看出,在达到60之前,数据呈指数形式增长。这称之为指数避让。


RTT 时间测量

最初的关于TCP的声明采用如下公式来更新RTT:

RR+ ( 1-α)M 

其中M是测量到的RTT值,每次测量完成时,将对R值进行更新。

同时RFC793推荐将超时重传的值RTO (retransmission time out):

RTO = R *β 

推荐的β值为2。

但是当采用这种RTT测量方法时,如果RTT变化较快的话,会无法跟上变化,从而导致不必要的重传。所以,提出了新的方法,同时计算均值偏差,两者组合使用。公式如下:


其中A表示的含义和之前的公式中的R相同。D表示的是变化量的大小。

这个公式中比较让人费解的一点是为什么Err要加绝对值符号。(留待以后再解决吧)


Karn's Algorithm

当某个数据进行了重传时,不用这个数据的RTT来计算RTO,因为不知道这个ack确认对应的是之前的数据,还是重传的数据。

发生了超时重传时,RTO会进行指数避让,这个时候就会保持这个RTO值不变,直到收到新的数据的确认才继续更新计算RTO值。


一个RTT example

书上讲了一个传输数据(中间发生了三次超时重传)的例子。

有以下知识点:

1.大多数TCP实现,对于同一个连接,在同一时间只会测量同一个RTT值。

2.用500ms溢出一次的定时器计时,保存的是溢出次数,所以时间会有0-500ms的误差。

3.RTT测量过程:发送数据时,开始计时,同时记录下发送数据的开始序列号,当收到包含此序列号的确认序列号时,计时停止,一次RTT测量完成。更新RTO。

4.发送第一个报文,也就是SYN报文时,A和D被分别初始化为0和3s,并且计算初始RTO公式如下(注意这是计算初始RTO,和后面介绍的初始测量得到M计算RTO并不相同):

RTO=A+2D=6s

所以,SYN报文的初始超时值是6s。

之后都会使用公式RTO=A+4D,并且遵循指数避让规则。

所以,如图4.5所示。

发送SYN报文时,第一次超时时间是6s,第2次是24s,因为当第一个报文超时后,首先RTO=A+4D重新计算RTO=12,再执行一次指数避让,得出结果为24。

再超时,RTO=48。上限为60。

5.初次测量得到M后计算RTO的公式如下:

A=M+0.5

D=A/2

RTO=A+4D

例子中,M=1.5,计算得到的RTO=6s。

弄了这么多复杂的公式,复杂的初始值,真不知道是为什么,还不如弄一个表呢,将初始的特殊情况写进去,然后再有一个普适的公式就行了。




拥塞举例

知识点:

当TCP的接收方收到乱序报文时,会重复发送之前已经收到的连续的报文的最大的序列号。而无法跳过中间没有接收的报文而确认新收到的报文,接收端会将这些报文缓存起来,等待丢失的数据到来后一起上交给应用程序。


拥塞避免算法

有一个前提条件假设:网络中由于错误(如Tcp,ip校验和等)而丢弃的报文远远小于所有报文的1%,也就是一般的丢包都是由于网络拥塞引起的。

有两种情况指示发生了丢包:1.超时重传计时器溢出 2.重复收到相同的ack序列号

拥塞避免和慢启动是两个独立的算法。他们都是关于如何维护拥塞窗口cwnd,但是具体的方法是不同的。慢启动是指数形式的增长,而拥塞避免是加法形式的增长。

一般的TCP实现都将这两个算法结合起来使用,需要维护两个变量:cwnd,ssthresh:

1.TCP连接建立之时,将cwnd初始化为1个报文段大小。ssthresh初始化为65535byte。

2.TCP输出例程的输出不能超过 cwnd和接收方通告窗口的大小

3.当拥塞发生时(超时或收到重复确认),ssthresh被设置为当前窗口大小(cwnd和接收方通告窗口大小的最小值)的一半,但ssthresh最少为2个报文段。此外,如果是超时引起了拥塞,则cwnd被设置为1个报文段(这就是慢启动)。(如果不是由于超时触发的重传呢?由书后面的内容推测,应该也是设置为1个报文段大小)
4.当新的数据被对方确认时,就增加cwnd,但增加的方法依赖于我们是否正在进行慢启动或拥塞避免。如果cwnd小于或等于ssthresh,则正在进行慢启动,否则正在进行拥塞避免。拥塞避免增加公式就不细写了,大致是线性增长。


快速重传与快速恢复算法
前提知识:当TCP接收端接收到乱序报文时,会立即发送ack确认,而不进行延迟,这样做的目的是尽快告诉发送端,自己接收到了乱序的报文,期待收到哪个序列号的报文。

快速重传与快速恢复算法 描述如下:

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

具体的计算过程参考教材。


ICMP差错

一般的实现处理方法是:
1.一个接收到的源站抑制引起拥塞窗口cwnd被置为1个报文段大小来发起慢启动,但是慢启动门限ssthresh没有变化,所以窗口将打开直至它或者开放了所有的通路(受窗口大小和往返时间的限制)或者发生了拥塞。
2.一个接收到的主机不可达或网络不可达实际上都被忽略,因为这两个差错都被认为是短暂现象。这有可能是由于中间路由器被关闭而导致选路协议要花费数分钟才能稳定到另一个替换路由。在这个过程中就可能发生这两个ICMP差错中的一个,但是连接并不必被关闭。相反,TCP试图发送引起该差错的数据,尽管最终有可能会超时(回想图21-1中TCP在9分钟内没有放弃的情况)。当前基于伯克利的实现记录发生的ICMP差错,如果连接超时,ICMP差错被转换为一个更合适的的差错码而不是“连接超时”。

重试的时间间隔一般是:3,6,12,24,48,60,60......


重新分组
T C P超时并重传时,它不一定要重传同样的报文段。相反,TCP允许进行重新分组而发送一个较大的报文段,这将有助于提高性能(当然,这个较大的报文段不能够超过接收方声明的M S S)。在协议中这是允许的,因为TCP是使用字节序号而不是报文段序号来进行识别它所要发送的数据和进行确认。







阅读全文
0 0
原创粉丝点击