TCP可靠传输的原理
我们都知道,TCP发送的报文段是交付给IP层传送的。但IP层只提供尽最大努力传输,因此是不可靠的,因此TCP必须采用适当的措施才能使两个运输层之间通信变得可靠。
理想的传输条件有以下两个特点:
1.传输信道无差错
2.不管发送方以什么样的发送速率,接收方都能来得及处理发送方发送的消息。
然而实际上并不存在这样理想的传输条件,因此我们必须采用一些必要的措施保证实现可靠传输。
停止等待协议
这里我们讨论单方向的发送和接受,设A为发送方B为接收方。A每发完一个分组就等待B收到分组的确认,然后才发送下一个分组。
上图a介绍了无差错的情况,b图展示若出现差错的应对机制,若B发给A的确认报文在途中丢失,B对于自己的报文丢没有并不清楚,它只等待A传入下个数据包,而A也在等B的确认报文,发现这种情况怎么办呢。超时重传了解一下,超时重传就是为了解决这个问题,当A在一定时间内没有收到B的确认,就认为自己发送的数据报文B没有收到,并且重发这段数据,如果这计时器规定时间内收到了A的确认就撤销计时器。
应当注意以下三点:
1.A没有收到B的确认报文时,必须暂时的保留已发送的分组副本,以便于超时重传。
2.分组和确认必须编码,这样才能知道哪些分组收到了确认,哪些没有收到。
3.超时计时器应当设计的比数据在分组传输的平均往返时间要长一些,如果重传时间过长会严重影响效率,但如果过短也会有不必要的重传,浪费资源。
确认丢失和确认迟到
若A没有收到B的确认报文,A并不知道是自己的分组丢失还是B的确认丢失,所以重传计时器超时就会重传分组。此时B又收到了分组
此时B有两个行动:
1.丢弃重复的M1,不向上层交付。
2.对A发送确认。
可是试想有这样一种可能如图b,B的确认并没有丢失而是由于网络延迟滞留在网络中。
此时A会受到重复的确认,处理也很简单。A对重复的=确认并不处理,B依旧会收到重复的分组,然后丢弃重复的M1,并给A发送确认。
使用以上的确认重传机制就能在不可靠的网络上实现可靠的通信。
TCP的滑动窗口
实际上为了提高信道利用率,分组传输并没有每次只发送一个分组,然后等待确认。(这样实在效率太低)。为了提高传输效率,我们必须采用流水线传输,流水线传输使得发送方可以连续发送多个分组,不必每发完一个分组,就停下来等待,显然这样就能获得较高的信道利用率。
使用流水线传输就要介绍TCP的滑动窗口,现在假定A发送数据B接收数据来讨论TCP的滑动窗口。
TCP的滑动窗口是以字节为单位的,现假设A收到了来自B的确认报文,其中窗口大小为20字节,确认号为31,而序号30以前的数据都被完好的接受了。
我们先说A的发送窗口,发送窗口表示在没有收到B的确认之前窗口里的数据都能持续的发送出去,但这些数据在没有收到B的确认时都必须保留下来,以便于超时重传。显然窗口越大发送方就能在收到确认之前持续发送更多的数据,可以获得更高的传输效率,前提是对方来得及处理这些数据。
滑动窗口后沿部分表示已发送并且已经确认的报文,这些可以不用在保留,而前沿部分表示不允许发送的,发送窗口由前沿和后沿共同决定,发送窗口的后沿就两种变化情况不动(没有收到确认),向前移动(收到确认)。发送窗口的前沿一般都是向前移动的,当然也可能不动(没收到确认,窗口值也不变,或者收到确认,窗口值变小)发送窗口前沿也可能向后收缩,这发生在对方通知窗口变小,TCP强烈不推荐这样做。因为可能已经发送了这些数据,但现在又不让发送,可能会产生错误。
现在假设A发送了31-41的数据,这时窗口未改变。灰色的小方框表示已经发送但没有收到确认的,而发送窗口后九个字节42-50表示没有发送但允许发送的。从上图看出要描述一个发送窗口需要三个指针:p1,p2,p3.
小于p1表示已经发送成功的,大于p3表示不可发送的
1.p3-p1表示发送窗口
2.p2-p1表示已发送尚未确认
3.p3-p2表示尚未发送的
再看B的接收窗口,接收窗口大小为20字节,B收到了32、33号的数据,没有收到31号所以B只能给出收到的数据最高序号加1,也就是31,期望下次收到31号数据。
现假定B收到了31号数据并对A确认,窗口依然是20,此时A可以向前移动3个字节,此时A的可发送窗口变大,发送范围为42-53.
A在继续发送完数据,p2指针p3指针重合此时发送窗口已满,但B的确认并没有到达(丢失或者滞留),等到重传计时器超时,就必须重传这部分数据。直到收到B的确认,然后继续滑动窗口。
TCP的缓存与窗口的关系:
小思考,若收到的报文段无差错只是没有按序号到达,中间还缺少数据,能否只重传缺少的数据而不用重传已经收到的数据?
答案是可以的,选择确定(SACK)是一种可行的办法。要使用选择确认,双方必须商定好,必须在TCP首部增加SOCK选项,以便报告收到不连续的字节块的边界以便于重传。