您的位置:首页 > 理论基础 > 计算机网络

计算机网络(七)--TCP的可靠传输原理及实现(一)

2017-03-03 19:35 591 查看
可靠传输的工作原理

TCP发送的报文段是交给IP层传送的。但IP层只能提供尽最大努力服务。所以TCP必须采用适当的措施才能使两个运输层之间的通信变得可靠。

理想的传输条件:

(1)传输信道不产生差错。

(2)不管发送方以多快的速度发送数据,接收方总是来得及处理收到的数据。

措施:当出现差错时让发送方重传出现差错的数据,同时在接收方来不及处理收到的数据时,及时告诉发送方适当降低发送数据的速度。由此用不可靠的传输信道实现可靠传输。

最简单的协议:停止等待协议

“停止等待”就是每发送完一个分组就停止发送,等待对方的确认。在收到确认后再发送下一个分组。(因为讨论可靠传输的原理,因此把传送的数据单元都称为分组)

全双工通信的双方既是发送方也是接收方。仅考虑A发送数据而B接收数据并发送确认。称为A叫做发送方,而B叫做接收方。

可靠传输协议的设计:A只要超过了一段时间仍然没用收到确认,就认为刚才发送的分组丢失了,因而重传前面发送过的分组。这就叫做超时重传

超时重传的实现:在每发送完一个分组设置一个超时计时器。如果在超时计时器到期之前收到了对方的确认,就撤销已设置的超时计时器

注意三点:

第一,A在发送完一个分组后,必须暂时保留已发送的分组的副本(为发生超时重传时使用)。只有在收到相对应的确认后才能清除暂时保留的分组副本。

第二,分组和确认分组都必须进行编号。这样才能明确是哪一个发送出去的分组收到了确认,而哪一个分组还没有收到确认。

第三,超时计时器设置的重传时间应当比数据在分组传输的平均往返时间更长一些

A在设定的超时重传时间内没有收到确认,情况有两种:

1)A发送的分组出错、丢失。

2)B发送的确认丢失了。

超时重传的情况有两种:

无论上述哪种情况,B收到重传的分组后,向A发送确认。若分组重复就丢弃,否则上交。(即B每次收到分组检测无误后,就向A发送确认,无论该分组是否重复。但重复的分组会被丢弃)

若B发送的确认迟到了(无论它是否在重传后收到B发送的第二份确认),A会收下重复的确认后丢弃。

像上述的这种可靠传输协议常称为自动重传请求ARQ(Automatic Repeat reQuest)。意思是重传的请求是自动进行的。接收方不需要请求发送方重传某个出错的分组。



停止等待协议的优点时简单,缺点是信道利用率太低。

为了提高传输效率,发送方采用流水线传输。当使用流水线传输时,就要使用下面介绍的连续ARQ协议滑动窗口协议



信道利用率: U = TD /(TD +RTT+TA)

TD为A发送分组需要的时间,其值为分组长度除以数据率。RTT是往返时间,其取决于所使用的信道。TA是B发送确认分组需要的时间。

若出现重传,则对传送有用的数据信息来说,信道的利用率就还要降低。

连续ARQ协议

发送窗口:位于发送窗口内的分组都可以连续发送出去,而不需要等待对方的确认。

分组发送是按照分组序号从小到大发送的。

连续ARQ协议规定,发送方每收到一个确认,就把发送窗口向前滑动一个分组的位置。

接收方一般都是采用累积确认的方式。接收方不必对收到的分组逐个发送确认,而是在收到几个分组后,对按序到达的最后一个分组发送确认,表示到这个分组为止的所有分组都已正确收到了。

缺点:不能向发送方反映出接收方已经正确收到的所有分组的信息。

TCP可靠传输的实现

为了讲述的方便,假定数据传输只在一个方向进行,即A发送数据,B给出确认。

TCP的滑动窗口是以字节为单位的。

A的发送窗口由收到的确认报文段中的窗口值确认号来构建发送窗口。

发送窗口表示:在没有收到B的确认的情况下,A可以连续把窗口内的数据都发送出去。凡是已经发送过的数据,在未收到确认之前都必须暂时保留,以便在超时重传时使用。

发送窗口的位置由窗口前沿和后沿的位置共同确定。后沿后面部分是已发送并收到确认,前沿前面部分是不允许发送的,因为接收方没有为这部分数据保留缓存。

发送窗口前沿通常是不断向前移动,也有可能不动(每收到新的确认,或收到新的确认但对方通知的窗口缩小了)。

发送窗口前沿也有可能向后收缩。但TCP的标准强烈不赞成这样做。因为很可能发送方在收到这个通知以前已经发送了窗口中的许多数据,现在又要收缩窗口,不让发送这些数据,这样就会产生一些错误。

由上述可见,描述一个发送窗口的状态需要三个指针:p1,p2,p3。

小于p1的是已发送并已收到确认的部分,而大于p3的是不允许发送的部分。大于等于p1到小于p2的是已发送但未收到确认,大于等于p2到小于p3的是允许发送但尚未发送。

接收方B只能对按序收到的数据中的最高序号给出确认。

发送方A在没有收到确认报文期间会做什么?,发送方会持续发送发送窗口的数据。若没有数据可以发送了,一定时间后仍未收到确认(超时),则重传这部分数据。(?不确定是第一个数据发送时会进行计时,还是没有数据发送时开始计时)

接收方B什么时候会给A发送确认?接收方B将收到的一部分按序的数据上交主机后,删除这些数据,移动接收窗口,然后给A发送确认。

发送方的应用进程把字节流写入TCP的发送缓存,接收方的应用进程从TCP的接收缓存中读取字节流。

第一,缓存空间和序号空间都是有限的,并且都是循环使用的。这里为了画图的方便,把它们画成长条状,同时不考虑循环使用缓存空间和序号空间的问题。

第二,由于实际上缓存或窗口中的字节数是非常之大的,无法在图中把一个个字节的位置标注清楚。



发送缓存用来暂时存放:

1)发送应用程序传送给发送方TCP准备发送的数据。

2)TCP已发送出但尚未收到确认的数据。

发送窗口通常只是发送缓存的一部分,已经确认的数据应当从发送缓存中删除,因此,发送缓存和发送窗口的后沿是重合的。

接收缓存用来暂时存放:

1)按序到达的、但尚未被接收应用程序读取的数据。

2)未按序到达的数据。

根据以上所得,强调三点:

第一,虽然A的发送窗口是根据B的接收窗口设置的,但在同一时刻,A的发送窗口并不总是和B的接收窗口一样大。这是因为通过网络传送窗口值需要经历一定的时间滞后(这个时间还是不确定的)。另外,发送方A还可能根据网络当时的拥塞情况适当减小自己的发送窗口数值。

第二,对于不按序到达的数据应如何处理,TCP标准并无明确规定。如果接收方把不按序到达的数据一律丢弃,那么接收窗口的管理将会比较简单,但这样做对网络资源的利用不利(因为发送方会重复传送较多地数据)。因此TCP通常对不按序到达的数据是先临时存放在接收窗口中,等到字节流中所缺少的字节收到后,再按序交付上层的应用进程。

第三,TCP要求接收方必须有累积确认的功能,这样可以减小传输开销。接收方可以在合适的时候发送确认,也可以在自己有数据要发送时把确认信息顺便捎带上。但请注意两点,一是接收方不应过分推迟发送确认,否则会导致发送方不必要的重传,这反而浪费了网络的资源。TCP标准规定,确认推迟的时间不应超过0.5秒。若收到一连串具有最大长度的报文段,则必须每隔一个报文段就要发送一个确认。二是捎带确认实际上并不经常发生,因为大多数应用程序不同时在两个方向上发送数据。

超时重传时间的选择

TCP的发送方在规定的时间内没有收到确认就要重传已发送的报文段。这种重传的概念是很简单的,但重传时间的选择却是TCP最复杂的问题之一。

原因:TCP的下层是互联网环境,发送的报文段可能只经过一个高速率的局域网,也可能经过多个低速率的网络,并且每个IP数据报所选择的路由还可能不同。如果把超时重传时间设置得太短,就会引起很多报文段的不必要的重传,使网络负荷增大。但若把超时重传时间设置得过长,则又使网络的空闲时间增大,降低了传输效率。

TCP采用了一种自适应算法,它记录一个报文段发出的时间,以及收到相应的确认的时间。这两个时间之差就是报文段的往返时间RTT。TCP保留了RTT的一个加权平均往返时间RTTs(这又称为平滑的往返时间,S表示Smoothed。因为进行的是加权平均,因此得出的结果更加平滑)。

每当第一次测量到RTT样本时,RTTs值就取为所测量到的RTT样本值。但以后每测量到一个新的RTT样本,就按下式重新计算一次RTTs:

新的RTTs = (1-a)* (旧的RTTs) + a * (新的RTT样本)

若a接近零,表示新的RTTs值和旧的RTTs值相比变化不大。若a接近1,表示RTT值更新较快。RFC2988推荐的a值为1/8,即0.125。

超时重传时间RTO(Retransmission Time-out)应略大于加权平均往返时间RTTs。RFC2988建议使用下式计算RTO:

RTO = RTTs + 4 *RTTD                     RTTD 
是RTT的偏差的加权平均值,它与RTTs和新的RTT样本之差有关。

新的RTTD = (1-p)*(旧的RTTD) +  p * | RTTs -   新的RTT样本|              p是个小于1的系数,推荐值是1/4,即0.25。

发送出一个报文段。设定的重传时间到了,还没有收到确认。于是重传报文段。经过了一段时间后,收到了确认报文段。

问题:如何判定此确认报文段是对先发送的报文段的确认,还是对后来重传的报文段的确认?

答:由于重传的报文段和原来的报文段完全一样,无法做出正确的判断,而正确的判断对确定加权平均RTTs的值关系很大。

解答:karn提出了一个算法,在计算加权平均RTTs时,只要报文段重传了,就不采用其往返时间样本。这样得出的加权平均RTTs和RTO就较准确

新问题:报文段的时延突然增大很多。因此在原来得出的重传时间内,不会收到确认报文段。于是就重传报文段。但根据Karn算法,不考虑重传的报文段的往返时间样本。这样,超时重传时间就无法更新。

解答:对Karn算法修正,报文段每重传一次,就把超时重传时间RTO增大一些。典型的做法是取新的重传时间为2倍的旧的重传时间。当不再发生报文段的重传时,才根据上面给出的公式计算超时重传时间。

Karn算法能够使运输层区分开有效的和无效的往返时间样本,从而改进了往返时间的估测。

选择确认SACK

若收到的报文段无差错,只是未按序号,中间还缺少一些序号的数据,那么能否设法只传送缺少的数据而不重传已经正确到达接收方的数据?选择确认就是一种可行的处理方法。

如果要使用选择确认SACK,那么在建立TCP连接时,就要在TCP首部的选项中加上“允许SACK”的选项,而双方必须都事先商定好。

由于首部选项的长度最多只有40字节,在选项中最多只能指明4个字节块的边界信息(4*2*4,序号有32位,一个边界需要4字节)。

另外需要两个字节,一个字节指明是SACK选项,另一个字节指明这个选项占用多少字节。

SACK文档并没有指明发送方应当怎样响应SACK。因此大多数的实现还是重传所有未被确认的数据块。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: