持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第9天
流水线可靠数据传输协议
rdt3.0,在功能上已经是一个完备的协议,但它的性能并不高,原因就在于它是一个停等协议,发送一个分组时单独占用一个信道,后一个分组必须等前一个分组传完之后才能传,也就是说发送方一次只能发送一个数据,它的信道利用率是极低的,就像这样:
我们解决这个问题的一个方法就是不以停等的方式运行,允许发送方发送多个分组无需等待,即:
发送方一次发送多个分组的方式称为流水线(pipeline)技术 ,对于流水线技术,我们应该注意:
- 增加序号范围,每个在传输中的分组必须有唯一序号,可见之前的0和1已经不能满足流水线的需求。
- 发送方和接收方需要缓存多个分组。
- 所需序号范围和对缓冲的要求取决于数据传输协议如何处理丢失、损坏以及延时大的分组。
其中第三点是摘抄的top-down原话,要很好的解释它,我们必须先引出滑动窗口的内容。
滑动窗口(Slide Window)协议
在了解什么是滑动窗口之前,我们先回忆一下之前的内容。rdt协议中,发送方一次发送一个分组,接收方一次接收一个分组。但是人们不满足rdt协议的性能,于是提出流水线技术,使发送方一次发送多个分组,所以发送方需要缓存多个分组,按照缓存区内分组的不同类型,我们大概可以分为以下几种:①已发送且被确认的分组 ②已发送但未被确认的分组 ③待发送的分组
我们把已发送但未确认的分组和待发送的分组的区域称为发送缓冲区,图中N即为缓冲区的大小
把已发送但未确认的分组构成的空间称为发送窗口。可以发现,发送窗口是发送缓冲区的一部分。
- 发送窗口的后沿等于发送缓冲区的后沿
- 发送窗口的前沿不超过发送缓冲区的前沿
- 之后讨论的移动是指发送窗口在移动,发送窗口在0-N之间变化
关于以上的内容在第一次写这篇文章时一直没想明白,就去科大底下提问了,郑老师也很好的解答了我的疑惑:
我们知道,rdt一次只能发送一个分组,所以sw = 1(send window我们简称为sw,接收窗口简称为rw),而流水线技术中,一次可以发送多个分组 ,所以sw > 1。而事实上,不仅是sw可以>1,接收窗口rw也可以>1,即一次接收确认多个分组。下面用一张表格来表示其中的关系:
| sw | rw | 协议 |
|---|---|---|
| sw = 1 | rw = 1 | rdt协议 |
| sw > 1 | rw = 1 | GBN协议 |
| sw > 1 | rw > 1 | SR协议 |
至此,我们再次回到那就摘抄的话:所需序号范围和对缓冲的要求取决于数据传输协议如何处理丢失、损坏以及延时大的分组。这句话的后半句是:解决流水线的差错恢复有两种基本的方法:回退N步(GBN)和选择重传(SR)。下面我们就分别来看一下这两个协议。
回退N步(GBN)协议
首先我们来考虑,在正常情况下GBN协议中发送方和接收方两窗口的互动。对于发送窗口,可以参考上面的图。
其中有以下几点需要注意:
-
因为rw = 1,GBN协议一次只能确定接收1个分组
- 所以GBN协议只能顺序接收,只有当收到最低序号的分组(代表顺序正确),才发送ACK给发送方
😴分割线-----------------------------------------------------------------------------------------------------
那么以上就是正常情况下GBN协议两窗口的互动,在开始讨论异常情况前,我们要先清楚,对于GBN,什么是异常情况?答案即为乱序以及丢失。在上面说到,GBN只能顺序接收,所以先收到乱序的分组,我们要有解决方法。而丢失就更不用说了。下面给出异常情况下GBN协议两窗口的互动情况:
-
收到乱序分组时,因为没有落入接收窗口的范围内,接收方只能丢弃。
-
重复发老分组的ACK给发送方后,发送方发后沿不移动,所以从上层新来的分组不能进入发送缓冲区。
-
GBN只有一个计时器,这点是和rdt不同的,定时器的工作机制为
- 如果收到一个ACK,此时还有已发送但未确认的分组,则定时器重新启动。
- 如果收到一个ACK后,没有已发送但未确认的分组了,则停止该计时器。
-
当触发超时重传后,发送方将重传所有已发送但未被确认的分组,这就是所谓的回退N步。
这样的工作机制保证了该定时器可以当做最早发送但未被确认的分组的定时器
关于GBN异常情况我们这里举一个栗子🌰:
发送方发送0,1,2,3,4,5给接收方,我们假设分组2会丢失,由于接收方只能顺序接收,所以流程为:
- 收到0,回复ACK0,后沿向右移动
- 收到1,回复ACK1,后沿向右移动
- 未收到2,2在中途丢失
- 收到3,因为2没到来,所以接收方只能丢弃3并继续回复ACK1,此时发送发收到ACK且仍有已发送但未确定的分组(2),于是定时器启动。此时后沿不动
- 收到4,回复ACK1
- 收到5,回复ACK1
- 某一时刻,定时器timeout,发送方重新发送2,3,4,5
最后我们再来通过GBN协议中发送方和接收方的FSM来梳理一下GBN协议
发送方
-
发送窗口初始值为0(nextseqnum - base)
-
收到上层rdt_send()调用后,判断是否在可发送范围内
- 在可发送范围内:发送,并启动定时器,前沿向右滑动
- 在可发送范围外:没法发送(发送缓冲区用完)
-
timeout超时:重新启动定时器,重传所有已发送但未确认的分组
-
收到确认:后沿向右滑动
选择重传(SR)协议
SR协议和GBN协议相同,都使用了流水线技术,使sw>1,SR和GBN的不同点在于,SR协议的RW>1,即SR协议可以接收确定多个分组。和发送窗口一样,SR协议也有接收窗口。
在正常情况下,SR协议的两窗口互动和GBN协议的相同,在之前我们也提到过,这两种的不同点在于处理异常情况的方式不同。因为SR的rw>1,可以确认接收多个分组,也就是说,如果收到乱序分组,不必抛弃,可以把它缓存起来。下面给出异常情况下SR协议两窗口互动:
除了接收窗口和GBN不同之外,SR协议为每个发送的分组都设置了一个定时器,不同于GBN协议只有一个定时器。这样在触发超时重传时,只需发送超时的那个分组即可。
这里拿GBN协议中举的栗子🌰继续看一下:
发送方发送0,1,2,3,4,5给接收方,我们假设分组2会丢失,流程为:
- 收到分组0,发送ACK0,后沿滑动
- 收到分组1,发送ACK1,后沿滑动
- 分组2在发送过程中丢失
- 收到分组3,发现是乱序,缓存起来,发送ACK3,后沿不滑动
- 收到分组4,发现是乱序,缓存起来,发送ACK4
- 收到分组5,,发现是乱序,缓存起来,发送ACK5
- 直到某个时刻,分组2的定时器timeout,重传分组2
对比GBN和SR
| GBN | SR | |
|---|---|---|
| 优点 | 简单,所需资源小(接收方一个缓存单元) | 出错时,只需重传1个,代价小 |
| 缺点 | 一旦出错,回退N步代价大 | 复杂,所需 资源多(接收方多个缓存单元) |
不难发现,GBN 和 SR 的优点和缺点是互相对应的,所以我们可以构想出它们的适用场景
- 出错率低时,适合GBN
- 链路容量大(延迟大,带宽大)时,适合SR,因为一旦出错GBN代价很大。