【计算机网络】3.3 可靠数据传输原理

第三章第三节 可靠数据传输原理

  信道通常指链接信号发送方和接收方的传输线路,包括双绞铜线等物理媒体。在实际的网络传输中,信道是不可靠的,在其上传输的分组可能会损坏或丢失,甚至相对次序都不能保证。网络

  TCP 这一 运输层协议 则提供了可靠的数据传输框架解决上述问题,其向上层(应用层)提供面向链接的可靠的服务。而TCP的下层是网络层,网络层提供的尽力而为的服务,也就是说不提供任何质量保证。简单来讲,TCP实现如下两个功能,即“可靠”的概念:传输的数据比特不会受到损坏或丢失;全部数据都是按照其发送顺序进行交付的。框架

  在本节中咱们仅讨论单向数据传输(unidirectional data transfer)的状况,介绍可靠传输协议、流水线协议、回退N步、选择重传。函数

Outline

Notes

## 可靠服务的模型

  • 上图就说明了用于数据传输协议的各个接口。
    • 运输层经过rdt_send()函数,调用数据传输协议的发送方,把数据交付给接收方的较高层。
    • 发送方的运输层调用udt_send()函数,将分组发送到不可靠的信道。
    • 当分组从信道的接收端到达接收端时,将调用rdt_recv()
    • rdt协议向较高层交付数据时,调用deliver_data()

 

## 通过彻底可靠的信道的 rdt 1.0

  有限状态机(FSM) 能够表示有限个状态及在这些状态之间的转移和动做等行为的数学模型,下图即表示发送方和接收方的有限状态机,底层信道是彻底可靠的,发送方和接收方有各自的FSM,每一个FSM都只有一个状态。性能

  (图解:FSM描述中的箭头指示了协议从一个状态变迁到另外一个状态。引发变迁的事件显示在横线的上方,事件发生时所采用的运动显示在横线的下方。FSM的初始状态用虚线表示。)spa

 

  • 发送端,只经过 rdt_send(data) 事件接收来自较高层的数据发送请求。在完成一次数据发送请求中须要两个动做:
    • 产生一个包含该数据的分组(经由 make_pkt(data) 产生)
    • 而后将该分组经过 udt_send(packet) 发送到信道中
  • 完成这两个动做后,从新返回原始状态,继续等待来自较高层的数据发送请求。
  • 接收端,rdt 经过 rdt_rcv(packet) 事件从底层信道接收一个分组。在一次数据接收过程当中一样须要两个动做:
    • 从分组中取出数据(经由 extract(packet, data) 产生)
    • 而后将数据上传给较高层(经过 deliver_data(data) 动做)
  • 和发送端同样,接收端完成这两个动做后也从新返回原始状态,继续等待从底层信道接收分组。
  • 值得注意的是,rdt的发送端是由较高层应用的调度产生的,接收端协议是由较底层协议的过程调度产生的
  • 在这个协议中,一个单元数据和一个分组没有区别。
  • 由于信道可靠,接收方也不须要提供任何反馈信息给发送方
  • 假定了接收方接收数据的速率可以与发送方发送数据的速率同样快,因此接收方也没有必要请求发送方慢一点发送。

 

## 经有比特差错信道的可靠数据传输: rdt2.0

  如今咱们能够假设在信道传输过程当中分组中的比特可能受损了,在这种比特可能受损的状况下,来看一下如何构造可靠数据传输协议 rdt 2.0。注意如今仍然假定全部发送的分组(即便受损)将按照其发送的顺序被接收,同时信道中的分组也不会丢失。code

  接收方收到分组之后,能够向发送方发送确定确认 (ACK) 或否认确认 (NAK) 。这些控制报文可让发送方知道哪些内容被正确接收,哪些内容接收有误并所以须要重复。这种基于重传的可靠数据传输协议被称为自动重传请求 (Automatic Repeat reQuest, ARQ) 协议blog

  ARQ协议须要三个功能来处理分组出错的状况:接口

  • 差错检测。咱们须要一种机制可以使接收方检测何时出现了比特差错。
    • 好比 UDP检验和 字段就是为了这个目的。
    • 这些技术要求有额外的比特从发送方发送到接收方,而这些比特将存放在 rdt 2.0 数据分组的分组检验和 字段中。
  • 接收方反馈。发送方要了解接收方是否正确接收分组的惟一途径就是让接收方提供明确的反馈信息
    • rdt 2.0 协议将从接收方向发送方回送 ACK 或 NAK 分组。
    • 这些分组在理论上只须要一个比特长,好比用 0 表示 NAK,用 1 表示 ACK。
  • 重传。若是接收方收到了受损的分组,发送方必须重传该分组。

【rdt2.0 自动重传请求协议】

  下图为rdt 2.0 的有限状态机描述图,该数据传输协议(自动重传请求协议)采用了差错检测、确定确认与否认确认。事件

  • 在发送端左边的初始状态中,发送端协议正等待来自较高层传下来的数据。当触发 rdt_send(data) 事件时:
    • 经过 sndpkt = make_pkt(data, checksum) 产生一个包含待发送数据且带有校验和的分组
    • 而后将该分组经过 udt_send(sndpkt) 发送到信道中
  • 执行完上述的两个动做后,发送端的状态变迁为“等待接收接收端的 ACK 或 NAK 分组”。即转变为右侧状态,接下来根据接收端的响应不一样会有不一样的变迁方案:
    • 若是收到了一个 ACK 分组(rdt_rcv(rcvpkt) && isACK(rcvpkt)),那么发送方知道最近一个分组已经被正确接收,所以协议返回左边状态,继续等待下一次由较高层传下来的数据发送请求
    • 若是收到了一个 NAK 分组(rdt_rcv(rcvpkt) && isNAK(rcvpkt)),那么发送端知道接收端接收到的分组是受损的,因此调用 udt_send(sndpkt) 从新发送该分组,而后状态不变,继续等待接收接收端的 ACK 或 NAK 分组。

  在上述协议中,当发送方处于等待ACK或NAK状态时,它不能从上层得到更多数据。这样子的协议被称为停等协议 (stop-and-wait)资源

  • rdt 2.0 的接收端仍然只有一个状态。状态变迁取决于收到的分组是否受损,有两种方式:
    • 若是收到的分组受损,即 rdt_rcv(rcvpkt) && corrupt(rcvpkt),则返回 NAK 分组
    • 若是收到的分组无缺,即 rdt_rcv(rcvpkt) && notcorrupt(rcvpkt),则返回 ACK 分组
  • 处理完后仍然返回自身这个状态,继续等待下一次从底层接收分组并处理。

 

【rdt2.1 解决 ACK/NAK 分组受损的引入序号的协议

  rdt2.1 彷佛是一个能够在有比特差错信道上正常工做的可靠数据传输协议了,但仔细想一想,咱们没有考虑 ACK 或 NAK 分组受损的状况。

  处理ACK/NAK分组损坏的方法有如下三种:

  • 增长控制信令: 即发送方请求接收方重复ACK或NAK分组。但新的控制信令也可能受损。
  • 增长足够的校验和比特: 使发送方不只能够检测差错,还能够恢复差错。对于会产生差错却不会丢失分组的信道,能够直接解决问题。
  • 重传当前数据分组: 发送方收到损坏的ACK或NAK分组时,重传当前数据分组。这种方法在信道中引入了冗余分组 (duplicate packet)。 这致使接收方不知道接收到的分组是新数据分组的仍是一次数据重传。

  想要解决这个问题,咱们须要在数据分组中添加一个新的字段,而后让发送端对其数据分组编号,将发送数据分组的序号放在该字段中。因而,接收端只须要检查序号就能够肯定收到的分组是不是一次从新传送的分组。

  咱们把引入序号的协议称为rdt 2.1,FSM图以下。

 

  • 按照上图来描述一下 rdt 2.1 协议发送端的状态变迁过程:
    • 首先由较高层触发 rdt_send(data) 事件,经过 sndpkt = make_pkt(0, data, checksum) 产生一个序号为 0,包含待发送数据且带有校验和的分组,接着经过 udt_send(sndpkt) 将其发送到信道中,而后状态变迁为“等待接收接收端的 ACK 或 NAK 0”
    • 当发送端收到了一个来自接收端的分组数据:
      • 若是该分组数据受损,或者接收到的是 NAK 分组,那么经过 udt_send(sndpkt) 从新传送刚才的序号为 0 的分组到信道中
      • 若是该分组无缺且收到的是 ACK 分组,那么发送端知道接收端已经成功接收了刚才发送的序号为 0 的分组,此时发送端状态变迁到等待较高层传下来的数据发送请求
    • 接着再次由较高层触发 rdt_send(data) 事件,经过 sndpkt = make_pkt(1, data, checksum) 产生一个序号为 1,包含待发送数据且带有校验和的分组,接着经过 udt_send(sndpkt) 将其发送到信道中,而后状态变迁为“等待接收接收端的 ACK 或 NAK 1”
    • 当发送端再次收到了一个来自接收端的分组数据:
      • 若是该分组数据受损,或者接收到的是 NAK 分组,那么经过 udt_send(sndpkt) 从新传送刚才的序号为 1 的分组到信道中
      • 若是该分组无缺且收到的是 ACK 分组,那么发送端知道接收端已经成功接收了刚才发送的序号为 1 的分组,此时发送端状态变迁到等待较高层传下来的数据发送请求(即回到本状态机的初始状态)
  • 接着再来描述一下 rdt 2.1 协议接收端的状态变迁过程:
    • 首先在初始状态上,接收端等待着接收由发送端发来的序号为 0 的分组数据
    • 接着由 rdt_rcv(rcvpkt) 从底层信道接收了一个分组数据:
      • 若是该分组受损(即 rdt_crv(rcvpkt) && corrupt(rcvpkt)),那么由 sndpkt = make_pkt(NAK, checksum) 产生一个附带校验和的 NAK 分组,接着由 udt_send(sndpkt) 发送回发送端
      • 若是该分组失序(即 rdt_rcv(rcvpkt) && notcorrupt(rcvpkt) && has_seq1(rcvpkt)),那么由 sndpkt = make_pkt(ACK, checksum) 产生一个附带校验和的 ACK 分组,接着由 udt_send(sndpkt)发送回发送端
      • 若是该分组无缺且顺序正确(即 rdt_rcv(rcvpkt) && notcorrupt(rcvpkt) && has_seq0(rcvpkt)),那么经过 extract(rcvpkt, data) 和 deliver_data(data) 将分组数据上传给较高层程序。接着,由 sndpkt = make_pkt(ACK, checksum) 产生一个附带校验和的 ACK 分组,由 udt_send(sndpkt) 发送回发送端
    • 接下来等待序号为 1 的分组的处理过程与上面相似,再也不赘述

 

【rdt2.2 只用ACK的协议】

  协议rdt 2.1 使用了确定确认和否认确认。当接收到正确的分组时,接收方发送一个“确定确认”,当接收到受损的分组时,发送一个“否认确认”。若是不发送NAK,而是对上次正确接收的分组发送一个ACK,也能够实现同样的效果。发送方若是接收到两个同样的ACK,就说明接收方没有正确接收到跟在被确认两次的分组后面的分组。
  咱们把只使用ACK的协议称为rdt 2.2,其FSM图以下。

  具体 rdt 2.2 的流程由于和 rdt 2.1 基本相似,故不赘述。

 

## 经具备比特差错的丢包信道的可靠数据传输:rdt 3.0

  在现实的网络环境中,除了比特受损外,底层信道还会丢包;有不少可能的方法能够解决丢包问题,这里咱们让发送方负责检测和恢复丢包工做。

  假定发送端传输一个数据分组,该分组发生丢失 或者 接收端对该分组的 ACK 发生了丢失。在这两种状况下,发送端都收不到应当到来的接收端的响应。因此,若是发送端愿意等待足够长的时间以肯定该分组缺失已丢失,则它只须要重传该数据分组便可。

  从发送端的观点来看,重传是一个万能灵药。为了实现基于时间的重传机制,须要一个倒数计时器 (countdown timer),在一个给定的时间量过时以后,可中断发送方。发送方须要作到:1)每次发送一个分组(包括第一次分组和重传分组)时,就启动一个定时器;2)相应定时器中断;3)终止定时器。

  下图是rdt 3.0的发送方FSM,该协议运行在可能发生出错和丢失的信道上。

rdt 2.2 协议中的接收端有限状态机描述图仍然适用于 rdt 3.0 协议,下面我仍然用文字来简要描述一下上图中的发送端发送分组流程:

  • 首先由较高层触发 rdt_send(data) 事件,经过 sndpkt = make_pkt(0, data, checksum) 产生一个序号为 0,包含待发送数据且带有校验和的分组,接着经过 udt_send(sndpkt) 将其发送到信道中并启动定时器,而后状态变迁为“等待接收接收端的 ACK 0”
  • 当发送端在“等待接收接收端的 ACK 0”的时候:
    • 若是收到了受损的分组(即 corrupt(rcvpkt))或者收到了 ACK 1(即 isACK(rcvpkt, 1),也就是收到了本身发送的上一个分组的 ACK),则直接忽略
    • 若是定时器时间到,则由 udt_send(sndpkt) 从新发送该分组并从新启动定时器
    • 若是收到了无缺的分组且 ACK 为 0,那么发送端知道接收端已经成功接收了刚才发送的序号为 0 的分组,直接中止定时器,此时发送端状态变迁到等待较高层传下来的数据发送请求
  • 注意在继续等待从较高层传下来的数据发送请求的过程当中,若是收到了任何分组数据包,都直接忽略,由于它们必定是冗余的
  • 接下来继续重复上面的流程,只是改变了序号,再也不赘述

 

## rdt 3.0 的性能分析

  假设有两台主机,分别位于美国西海岸和东海岸,端对端延时 大约为 30ms,假定它们经过一条速率 R 为 1Gbps 的信道相连。包括首部字段和数据的分组长 L 为 1KB (8000 bits),因此发送一个分组进入 1Gbps 链路实际所需

  若是发送方在 t=0 时刻开始发送分组,则在 8μs 后,最后1bit进入了发送端信道。通过 15ms 后,分组的第一个 bit 到达接收端;在 15.008ms 时刻,分组的最后一个 bit 到达接收端。假设接收端的 ACK 产生和发送不占用时间,则再通过 15ms 之后,即t=30.008ms,发送端接收到接收端的ACK,发送端能够发送下一个分组。

  在 30.008ms 内,发送方的发送使用了0.008ms。咱们定义信道利用率为:发送方实际忙于发送比特到信道的时间与发送时间之比,则中止等待协议的发送方利用率为:

  在1G连路上每30毫秒才发送一个分组(33KB/s),这就是网络协议限制了物理资源的利用的例子。

 

##  可靠数据传输协议的技术

   校验和序号定时器确定和否认确认分组,这些技术都在协议的运行中起到了必不可少的做用。如今 rdt 3.0 已是一个功能正确的协议,但由于它的本质仍然是停等协议,因此效率实在捉急。在本笔记的下篇中,将介绍流水线可靠数据传输协议、回退 N 步协议以及选择重传协议,最终将会获得一个可靠而且效率较高的协议实现方法。

相关文章
相关标签/搜索