1.概述
为方便描述可靠传输原理,假定数据传输只在一个方向上进行,即A发送数据,B给出确认
2.以字节为单位的滑动窗口
TCP的滑动窗口是以字节为单位的。为了便于说明,字节编号取得很小。先假定A收到B发来的确认报文字段,其中窗口是20字节,而确认号是31字节。(表明B期望接收到的下一个序号是31,序号30之前的数据已经收到了)。如图所示。
- A的发送窗口:
发送窗口表示:在没有收到B的确认的情况下,可以连续把窗口内的数据发送出去。凡是已经发送过的数据,在未收到确认之前都必须暂时保留,以便超时重传使用。
发送窗口有如下特点:
1)发送窗口里面的序号表示允许发送的序号(如31~50)
2)发送窗口的位置由窗口的前沿和后沿的位置共同确定。发送窗口的后沿可能不动(没有收到确认),或者前移(收到新的确认)。发送窗口的前沿通常是不断的向前移动,但也可能不动。
现在假定A发送了序号为31-41的数据,如上图所示,图种可以看出要描述一个发送窗口的状态需要三个指针P1, P2, P3。
小于P1的是已发送并收到确认的部分,大于P3的是不允许发送部分。
P3-P1 = A的发送窗口(又称为通知窗口)
P2-P1 = 已发送但尚未收到确认的字节数
P3-P2 = 允许发送但尚未收到的字节数(又称为可用窗口或有效窗口)
- B的接收过程:
B的接收窗口大小为20。在接收窗口外面,到30号为止的数据均发送过确认并交付主机使用,因此B不再保留(之前的数据)。
如图所示,B收到了32和33的数据。这些数据没有按序到达,因为序号为31的数据没有收到。由于B只能对按序到达的数据中的最高序号给出确认,因此B的发送的确认号仍然是31,而不能是32或33。现在假定B收到序号为31的数据并把序号为31-33的数据交付给主机,然后B删除这些数据。接着把接收窗口向前移动3个序号,同时给A发出确认。其窗口值仍未20,但确认号34,表明B已经接收到序号33为止的数据。而B收到的37 38 40的数据没有按序到达,先暂存在接收窗口中。
如果按照以上的方式进行发送数据。当发送窗口已满,可用窗口减小到0,因此发送停止。如果发送窗口内所有数据都正确到达B,而发出的确认由于网络问题没有到达A,为保证传输,此时A只能认为B还没有收到这部分数据。于是A经过一段时间过(由超时计时器控制)重传这部分数据,直到收到B的确认为止。
3.缓存机制
发送方的应用进程把字节流写入了TCP的发送缓存,接收方的应用进程从TCP的接受缓存中读取字节流。下面进一步谈论窗口与缓存的关系。注:缓存空间和序号空间都是有限的并且循环使用的。
- 发送缓存和发送窗口
发送缓存用来暂时存放:1.发送应用程序传送给发送方TCP准备的数据2.TCP已发送但尚未收到确认的数据。
发送窗口通常只是发送缓存的一部分。已被确认的数据应当从发送缓存中删除,因此发送缓存与发送窗口的后沿是重合的。发送应用程序必须控制写入缓存的速率,不能太快,否则发送缓存就会没有存放数据的空间。
- 接收缓存与接收窗口
接收缓存用来暂时存放:1.按序到达的,但尚未被接收应用程序读取的数据。2,未按序到达的数据。
如果收到的分组检测出有差错,则要丢弃。如果接收应用程序来不及读取收到的数据,接收缓存最终就会被填满。使接收窗口减小到0.反之,接收应用程序能够及时从接收缓存中读取收到数据,接收窗口就会变大,但最大也不能超过接收缓存的大小。
4.超时重传的时间选择
TCP每发送一个报文段,就对这个报文段设置一次计时器。只要计时器设置的重传时间到还没有收到确认,就要重传这个报文段。由于数据链路层和运输层的往返实验概率分布存在很大差异,因此有必要选择合适的超时重传时间。
报文段的往返时延是指收到确认报文的时间与每一个报文段发出的时间之差。报文段的平均往返时延RTT是由各个报文段的往返时延样本加权平均得出来的。计算公式为:
平均往返时延RTT=α×(旧的RTT)+(1-α)×(新的往返时延样本),1 ≤ α < 1 典型的值为α为7/8.
即使有一个好的RTT,要选择一个合适的超时重传时间RTO(Restransmission Time out)仍然不是一个容易的事情。, 显然RTO要大于RTT。其计算公式为 RTO = β × RTT, β > 1, 推荐是2
5.选择确认SACK
若收到的报文段无差错,只是未按序号,中间还缺少一些序号的数据,采用选择确认的方法来传送缺少的数据,而不重传已经正确接收到的数据。
用一个例子来说明(Selctive ACK)工作原理。如图所示,接收放收到了前面的字节流不连续的两个字节块。如果这些字节的序号都在接收窗口内,那么接收方就先收下这些数据,但要把这些信息准确的告诉发送放,使发送方不要在重复发送这些已经收到的数据。
TCP首部没有哪个字段能够提供上述这些字节快的边界信息。如果要使用选择确认,那么在建立TCP连接时,就要在TCP首部的选项上加上“允许SACK”的选项。