rdt2.x协议提供了在只有比特错误的信道上的可靠传输服务。
书中提供了几个很巧妙的有限状态机,但是关于这几个有限状态机的设计逻辑却提及较少,所以本文先进行一些书中基础概念的引入,进行梳理,然后对关于rdt2.x协议的设计逻辑进行详细描述。
基本概念:
比特错误:分组中的可能会由0变为1,或由1变为0。
冗余分组:一个已经接收的分组再次到达。
序号:为分组编号,通过在分组中添加一个序号字段来实现。在rdt2.x中的目的是为了检测冗余分组,并且只用了[0,1]范围内的序号。
肯定确认:在收到一个正确的分组时,向发送主机发送一个分组,用于告诉发送主机刚才发送的分组正确送达。
否定确认:接受到一个分组后,向主机发送一个分组,这个分组的含义被双方解释为具有某些否定意义。
停等协议:在作为接收方的一端未正确的接收到本次发送的分组时,发送方不会发送下一个分组的协议。
自动重传请求协议:基于肯定确认或否定确认来实现重传,以达到可靠数据传输的协议被归类于ARQ协议。
为什么在rdt2.x中序号只需要1bit即可?
我们在rdt2.x中引入序号是为了让接收方检测冗余分组,也就是说,一个可能出现冗余的分组所携带的序号,在这个分组被确认无误的接收前,不会被一个新的分组去使用即可。
简单点说就是当使用序号 0 时,不会有一个新的分组去使用序号 0。
例如:发送方发送了 分组0 ,这个分组无误送达,可是接收方返回的 ACK 出现比特错误,此时发送方有限状态机的状态为等待 分组0 的确认报文, 接收方状态为等待 分组1 送达,此时不会有新的分组去使用序号0。
我们可以把1bit的序号看作一个环:,循环使用这些序号,因为我们的协议是一个停等协议,为每一个分组分配一个序号的话,那么在未确定序号为
的分组是否被正确接收时,不会发送序号为
的分组,所以发送方的有限状态机只会停在等待确认分组 N 的状态下,此时收到一个 ACK 或者 NAK 可以保证是对分组 N 进行确定的。
而接收方
即便是 rdt2.2 中的冗余 ACK ,仍然可以使用 1bit 的序号。假设发送方发送分组0,但在传输过程出现了比特错误,此时接收方会发送一个 ACK1 报文,此时发送方完全可以断定是分组0出现了错误,而没有什么其他含义。
有限状态机的几个状态:
首先,发送方有四个状态,其中两个为等待 ACK 的状态,即等待 分组0 和 分组1 的确定报文的状态,只有接收到一个含义为确定分组 n 被正确接收的报文时,发送方才会进入下一个状态。
如果接收到一个表示发送的分组出错的报文或有比特错误的确认分组时,那么我们使发送方直接重传这个分组,继续在此状态下等待对这个分组的确认。(这是我们采取的重传策略)
而接收方只有两个状态,等待 分组0 和 等待 分组1的两个状态。
在只有比特错误的信道上可能出现的事件:
- a. 分组发送过程中无误,且ACK报文无误。
- b. 分组比特错误,接收方通过冗余校验码检测到比特错误,并返回一个NAK报文,NAK报文无错。
- c. 分组比特错误,接收方通过冗余校验码检测到比特错误,并返回一个NAK报文,NAK报文出错。
- d. 分组无错,ACK报文比特错误,发送方无法识别这个报文的含义,不知道自己刚才所发送的分组是否被正确接收。
下面来对每个事件所产生的结果进行分析,这是也是对有限状态机逻辑设计:
(为了使协议更具有通用性,所以下面我们使用 n 来代替 0 或者 1 这两个序号)
a. 由于分组正确接收,且发送方得知了此消息, 故接收方和发送方有限状态机进入 (n + 1) mod 2 状态,等待下一个分组的发送。
b. 由于发送的分组产生了错误,所以接收方会等到这个分组的重传,不会进入下一状态。而发送方接受到一个 NAK 分组后保持原状态,并重传这个分组,等待对这个分组的确认。
c. 由于发送的分组产生了错误,所以接收方会等到这个分组的重传,不会进入下一状态。而发送方接受到一个出错的确认报文,并不知道自己所发送的分组是对是错,根据我们的策略,这里发送方直接重传,然后等待一个 ACK 。
e. 分组没有出错,被接收方接受,接收方进入等待序号 (n + 1) mod 2 的状态,同时返回一个 ACK 。但是 ACK 在发送过程中出现了比特错误,所以发送方不知道自己所发的分组是否正确接收,根据策略,发送方重发分组 n,并等待对分组 n 的确认,自然也不会进入发送序号为 (n + 1) mod 2 的状态。
由于先前接收方已经接收了分组 n ,所以发送方重发的这个分组就是一个冗余分组,不过接收方可以通过序号来辨识出这是一个冗余分组,即在等待(n + 1) mod 2 分组状态下,接收到一个序号为 n 的分组,接收方就认定为是一个冗余分组,因为在只有比特错误的信道模型中,这种情况只可能是 ACK 出了错误。
综上所述,接收方在等待 ACK 时,接收到了 NAK 或者出错的确认报文,就可以重传。而接收方是在等待 分组N 状态下,可能会接收到错误的 分组N, 此时返回一个 NAK 即可,还有可能接收到一个 分组 (N-1) mod 2, 此时只可能是之前的* ACK* 出现比特错误,接收方知道这种情况发生原因,所以在这种情况下就返回一个 ACK,使得接收方进入下一状态。
在rdt2.2中,可以使用冗余 ACK 来代替 NAK ,是因为在发送方使用序号 N 时,不会有一个新的分组再次使用序号 (N + 1) mod 2 = (N - 1) mod 2,所以一个冗余的 ACK 送达,发送就可以明确的知道分组 N 出现了比特错误。
所以在发送方一端,可以直接将触发重传的事件由接收到 NAK 改为接收到 冗余ACK。
而在接收方就有些巧妙了,在等待 分组N 送达状态下:
- 接收到出现比特错误的 分组N,此时发送方在等待 ACK N状态下,接收方要返回一个冗余的 ACK (N - 1) mod 2,来通知发送方重传 分组N。
- 接收到冗余 分组ACK (N - 1) mod 2,此时原因很明确,上面已经说了,是因为对分组的确认报文出现了比特错误。此时接收方停在等待 ACK (N - 1) mod 2 状态,所以要返回一个失序的 ACK,让发送方进入下一状态。
- 当对上一个分组的确认报文出错时,发送方重传这个分组,接收方可能接收到出现比特错误的 分组ACK (N - 1) mod 2(这里我们假设接收方在 等待 分组N 状态下)。
因为分组出现了比特错误,所以接收方不知道这个分组究竟是一个冗余分组,还是一个新的分组。这也是接收方有限状态机最巧妙的地方,此时可以发送一个 ACK (N - 1) mod 2(对于接收方来说,这是冗余的,因为在进入 N 状态前,一定发送过一个 ACK (N - 1) mod 2 ),这不会使有限状态机出现任何逻辑错误。
假设这个比特错误的分组是一个冗余分组,那么发送方此时在等待 ACK (N - 1) mod 2 状态下,即便发送方重发的分组时错误的,因为接收方此前已经正确收到了一个 分组(N - 1) mod 2,所以接收方可以使发送方直接进入下一状态。
另外一种情况是这个比特错误的分组是一个新的分组,所以发送方应该在 等待 ACK N 状态下,此时接收方发送一个 ACK (N - 1) mod 2,自然而然使得发送方重传这个分组了。
所以,在接收方收到一个错误的分组时,或是收到一个失序的分组时,都可以发送一个冗余 ACK 来作为回应,这不会产生任何逻辑错误。