运输层:可靠数据传输原理(FSM 描述)

禁止码迷,布布扣,豌豆代理,码农教程,爱码网等第三方爬虫网站爬取!

可靠数据传输原理

可靠数据传输的关键在于数据不错、不丢、不乱,可靠数据传输为上层实体提供的服务,可以抽象为数据通过一条可靠的信道进行传输。在可靠信道的保护下,传输的数据比特流不会被损坏或丢失,而且所有分组都会按需交付。

但是实际上并没有所谓的可靠信道,网络层的 IP 协议是不可靠信道,不可靠的信道实现可靠的传输需要双向控制信息流动。因此就需要一种可靠数据传输协议(rdt)在不可靠信道上提供可靠信道传输,信道的不可靠性决定了可靠数据传输协议的复杂性。因此对可靠数据传输协议的考虑,需要从简单到复杂的情景进行强化。

经完全可靠信道

首先考虑最简单的情况,此时的下层信道是可靠信道,也就是说信道满足不发生错误、不丢弃分组的条件。因此对于可靠信道,数据的发送端和接收端仅需要完成数据的发送、接收工作。

发送端

由于信道完全可靠,因此发送端仅需要完成数据发送的工作。其对应的 FSM 仅有一个状态,完成一次数据发送工作之后,状态就返回其自身。

接收端

由于信道完全可靠,因此接收端仅需要完成数据接收的工作。其对应的 FSM 仅有一个状态,完成一次数据接收工作之后,状态就返回其自身。

由此可见当信道是完全可靠时,发送端和接收端不需要任何反馈机制,也不需要任何查错机制。

经具有比特差错信道

自动重传请求协议

现在考虑信道并不可靠,而是会发生比特差错的情况,也就是经过信道的数据可能会发生位错误。此时为了反馈比特差错的发生,协议需要引入反馈机制,也就是使用肯定确认否定确认报文来反馈传输的情况,若收到了否定确认就需要重传数据报。引入反馈机制和重传机制的协议称之为自动重传请求协议
具体这个协议需要什么机制来实现?需要以下 3 种功能:

  1. 差错检测:在数据分组中加入校验和,通过校验和进行查错;
  2. 接收方反馈:接收方接收数据时,需要向发送方发送反馈信息,即为发送 ACKNAK。一般来说只需要 1 个比特长来表示,0 表示 NAK,1 表示 ACK;
  3. 重传:当数据出错时,发送方需要支持数据重传。

发送端

在引入反馈机制和重传机制后,发送端就需要 2 个状态来进行工作。首先第一个状态用于等待上层的调用,并进行数据发生的工作,发送数据时需要封装校验和。当数据发送成功后,就需要切换到下一个状态,此时协议需要等待接收端的反馈信息。若收到的信息是 NAK,则发送端需要重传数据,但是此时状态不发生改变。只有接收端发来 ACK 表示数据成功接收后,就可以回复到第一个状态。

我们可以观察到当发送方等待反馈信息时,不能够进行发送数据的任务,仅有等待到 ACK 之后才能切换状态。因此这种行为,协议也可以被称之为停止-等待协议

接收端

对于接收端而言只需要 1 种状态,但是该状态需要针对数据的正确性,而做出不同的应答。当通过校验和发现数据出错时,发送 NAK 要求发送方重传,当经过校验确认信息无误时,发送 ACK 表示数据成功接收。

现在的自动重传请求协议,可以实现可靠数据传输吗?

考虑应答报文出错

上文的自动重传请求协议存在一个关键的漏洞,既然数据分组会出错,那么 ACK 或 NAK 分组也同样会有出错的可能。此时有 3 种方案可以考虑:

  1. 增加校验和,对应答报文也使用校验和进行校验,但是发送端会困惑于这是对数据接收的反馈,还是对确认反馈的反馈;
  2. 增加额外控制信息,通过更多的信息令发送方不仅可以查错,也可以进行错误修复,但是额外的信息也有可能出错;
  3. 对于不正确的应答报文,直接重传,但是这么做会给接收方引入冗余分组,接收方无法确认冗余分组的顺序。

综上所述,这些方法都有不足之处,如何使上述方法具有可行性?现实中广泛应用的做法是添加序号字段,通过序号接收方就可以确认收到的分组是否是重传过的,这样发送发对于含糊的应答报文就可以放心地重传。序号仅需要区分前一个分组和现分组,因此有 0 和 1 两种序号,用于标记现在想收到的分组序号是 0 还是 1。这样当发生了因应答报文出错而引发的重传,接收方就可以通过序号来判定是否是冗余分组,进行主动丢包了。

发送方

由于引入了 2 种序号,发送方的状态将随之翻两倍,用于分别处理 0 和 1 两种序号的数据。此时与上文不同在于,发送方需要为每个分组加上序号,然后对 ACK/NAK 报文进行校验,发送方需要记住当前发送的分组序号以备重传。

接收方

由于引入了 2 种序号,接收方的状态将随之翻两倍,用于分别处理 0 和 1 两种序号的数据。接收方虽然不能知道反馈信息是否被成功接收,但是可以通过判断分组是否重复(当前所处状态的分组序号是否是期望分组序号)来配合发送方的重传。

仅使用 ACK

引入了序号之后,我们能不能实现不依靠 NAK,仅使用 ACK 来完成可靠传输呢?这种想法是可行的,此时当收到错误的分组时,接收方不发送 NAK,而是发送 ACK + 上一个正确分组的序号。当发送方收到同一个分组的 2 个 ACK 时也可以判断出接收方没有收到被确认 2 次的分组后的所有分组,此时就需要进行重传。

经具有比特差错的丢包信道

比特交替协议

上文我们解决了数据发生比特错误的问题,但是在实际情况下有可能分组并不是发生错误,而是直接在某个地方被丢弃了。根据停止等待协议,当发送端在等待 ACK 时,并不能处理后续的数据,而如果分组发送时发生了丢包,接收端将永远等待数据的传输,不会发送 ACK;若接收端发送了 ACK,但是 ACK 发生了丢包,则发送端也会永远等待下去。也就是说,如果没有发现丢包,有可能协议就不进行工作了。
此时对于协议而言,就需要考虑如何发现丢包的情况,以及丢包之后要怎么做。我们可以让发送端来负责对丢包的检测,当上述情况发生时,发送方都不会受到 ACK。所以若发送方等待足够长的时间没有收到 ACK,那么在逻辑上就可以认为发生了丢包,此时仅需要重传分组即可。为了基于时间来判断是否重传,发送方需要一个倒计数计时器,发送方需要做到每发送一次分组就启动一次计时器,等待一段时间没收到 ACK 就重传并重启计时器,收到 ACK 后终止计时器。

现在再考虑一个问题,若接收方收到了分组,而 ACK 也没有丢包,但是经历了超过计时器限定的时间的较大时延才被发送端接收的情况。这个问题在上述的自动重传请求协议已经解决,即使发送端重传了数据,接收端也可以使用序号来对于冗余的数据分组。由于分组序号在 0 和 1 之间交替,该协议也被称为比特交替协议

流程分析

传输过程无丢包

分组丢包

ACK 丢包

ACK 超时接收


到此为止,我们得到了一个可靠数据传输协议!

参考资料

《计算机网络 自顶向下方法》 [美] James F.Kurose,Keith W.Ross 著,陈鸣 译,机械工业出版社

posted @ 2020-07-07 19:42  乌漆WhiteMoon  阅读(1414)  评论(0编辑  收藏  举报