可靠数据传输协议
我们知道,TCP和UDP都是基于IP网际协议来传输数据的,但是IP网际协议是一种不可靠数据传输协议,它不负责数据丢失等情况,而TCP是一种可靠数据传输,因此我们需要来关注TCP是如何实现可靠数据传输的
经完全可靠信道的可靠数据传输:rdt1.0
rdt的假设前提是我们的数据在底层信道的传输是不会出现丢失和出错的,那么我们定义一个概念
可以预想到,rdt1.0的FSM肯定是很简单的,因为底层信道就实现了可靠数据传输(假设的)
rdt1.0的发送方和接收方的FSM如下:
经具有比特差错信道的可靠数据传输:rdt2.0
实际中在信道传输的数据是很有可能受损的,这个时候我们应当让发送方重传该分组,那么发送方如何知道是否重传一个分组呢?
-
ACK:当接收方收到一个分组时,如果该分组没有比特损伤,那么就给发送方发送一个ACK表示肯定确认,ACK可以用1比特的1表示
-
NAK:当接收方收到一个损伤的分组时,就给发送方发送一个NAK表示否定确认,NAK可以用1比特的0表示
基于这样重传机制的可靠数据传输称为自定重传请求(ABQ)协议
我们看一下rdt2.0的FSM
当发送方没有收到ACK或者NAK时,它是无法被上级调用的,所以rdt2.0这样的协议被称为停等协议
rdt2.0协议看起来好像是可以运行了,但是我们没有考虑到ACK和NAK出错的情况,当这两个分组出错时,发送方就无法确认发送的分组是否已经被成功接收了
rdt2.1
我们可以为ACK和NAK分组加上差错检测,这样可以解决问题
如果我们使用一个定时器,当一个分组超过时间还没收到NAK或者ACK,那么就将该分组重新发送,但是定时出现的一个问题就是,接收方并不知道这个分组是重传的还是新传的
这时候我们就可以使用序号来区分分组了,因为是分组是发送一个接收一个,所以我们只需要用序号0和1就能够区分出分组
- 当发送方发送一个分组序号为0的分组时,它会等待一个ACK 0来确保接收方收到了分组0,如果收到了ACK0发送方接下来就发送序号为1的分组,依次循环
- 当接收方收到一个分组序号为0的分组时,他会发送一个ACK 0分组来确认收到
我们来看rdt2.1的FSM
当然,我们不一定需要NAK,只要接收方发送前一个序号的ACK也能跟NAK起到同样的效果
比如说,当接收方收到序号为1的分组,但是该分组的比特受损了,因此我们需要发送方重新发送序号为1的分组,这时接收方只要发送一个ACK 0就可以了,发送方收到ACK 0就会重发序号为1的分组
基于无NAK的rdt2.2的FSM如下
rdt2.0协议是在底层信道不丢包的情况下展开的,但是底层信道是很有可能会丢包的,当出现丢包时,我们应当如何设计可靠数据传输协议
经具有比特差错的丢包信道的可靠数据传输rdt3.0
比较简单的实现方法就是为定义一个计时器,当出现超时事件时就重传该分组
rdt3.0发送方的FSM
rdt3.0虽然是一个正常的协议,但是它并不是很好,因为它的本质还是停等的,也就是发送一个接收一个,在确保接收之前它是不会发送其他分组的,更理想的情况是,我们希望分组是流水线的发送的,而不是停等
回退N步
在回退N步(BGN)协议中,我们先定义几个量
-
base: 最早未确认分组的序号
-
nextseqnum: 最小的未使用序号
因此我们知道
[0,base-1]是已发送且确认的分组
[base,mextseqnum-1]是已发送但未确认的分组
[nextseqnum,base+N-1]待发送的分组
我们将BGN称为滑动窗口协议
也就是每当序号为base的分组收到了ACK时,就将窗口[base, nextseqnum-1]向右滑动
当base+N==nextseqnum时,表示窗口已满,上层不能再发送分组
BGN协议的FSM
回退N步的意思就是,当有一个分组触发超时机制,就将滑动窗口中的所有分组重传
你可能不是很理解这个有什么意义,这个的意义在于,接收方不用对接收到的分组重新排序,因为当接收方收到一个分组时,该分组前面序号的可能丢包了,如果接收方对该分组缓存,那就需要其他的协议来处理如何将其排序
因此接收方只要接收序号是已接收的下一个就可以了,如果接收到的包不是上一个递交的包的下一个,那就直接丢弃该包
因此GBN协议自然而然的就将接收到的包按序递交了
选择重传
你可能会觉得接收方将所有不按序的包都丢掉很蠢,实际上这个协议确实有缺点每丢一个包时,就要重传滑动窗口中的所有包,当滑动窗口很大时,将会导致信道中充满了冗杂的分组,因此我们引出了选择重传的概念
选择重传的实现
当接收方收到一个分组时,将其缓存起来,然后对发送方发送一个ACK(这一步是必要的,因为如果发送方没有收到这个ACK,那滑动窗口就没办法向右滑动了),当接收方收到一个序号为base的分组,就将该分组以及它后面的之前收到的连续的分组一并递交上去,同时滑动窗口
选择重传中,发送方和接收方的滑动窗口是不一样的
因为接收方虽然收到了一个失序的分组,但是它的窗口不会滑动,而发送方收到了接收方发送的ACK,则会滑动窗口,这样双方的滑动窗口就不一样,当两者的滑动窗口不一样时,会出现什么问题?
简单来说,就是当接收方的滑动窗口滑倒下一次序号的开始,而发送方的滑动窗口却还在前一次的序号中,那接收方就不知道接收到的分组是新传的还是重传的
因此,滑动窗口的大小应该小于等于序号空间大小的一半
参考:
《计算机网络自顶向下方法》