一、概述

我们都清楚,网络层 IP 协议只是 尽最大努力交付,是不可靠通信协议。在 网络层之上是运输层,有两个重要的协议,分别是 UDP 和 TCP。UDP 和 IP 协议类似,也是不可靠传输。因此,TCP 作为可靠性协议应运而生。
对于理想的通信而言,需要做到以下两点:

  • 传输的信道不产生差错。
  • 无论发送方以多快速度发送,接收方都来得及接收并处理数据。

在这样的理想条件下,不需要采取任何措施就能实现可靠传输。但实际网络情况错综复杂,并不存在理想的通信传输,因此,需要采取一些措施保障双方通信是可靠的。比如当出现差错时让发送方重传差错数据,同时在接收方来不及接收处理收到的数据时,及时告知发送方应适当降低发送数据的速度。这样一来,原本不可靠的传输信道就能够实现可靠传输了。
可靠传输服务特点:

  • 无结构字节流。即没有边界,内容任意。
  • 虚电路连接。尽管 IP 网络是无连接的,但在 TCP 的端点上,却可看作是面向连接的通信—端到端通信。
  • 有缓冲的传送。提高传输效率。
    • 应用进程: 使用自己认为适宜的任何大小的数据片(最低1字节)。
    • TCP协议软件: 根据网络情况选择适当的收发缓冲区(合并/分割)。
    • Push: 强制滞留数据的发送。
  • 全双工服务。

TCP 的可靠性

  • 按序
  • 无差错
  • 不丢失、不重复

差错控制

  • 检测: 校验和、确认、超时
  • 纠正: 重传

TCP 可靠性保证

  • 采用面向连接的通信方式
  • 滑动窗口协议,以提高通信性能
  • 捎带确认方式
    • 未使用显示确认,减少报文种类
  • TCP 只有一种报文格式,完成
    • 建立、拆除连接
    • 数据传输
    • 确认、流量控制、窗口滑动

TCP主要提供了以下方法实现可靠传输。

  • 检验和。
  • 序列号/确认应答。
  • 超时重传。
  • 最大消息长度。
  • 滑动窗口控制

下面从协议的演变讲述 TCP 可靠传输。 TCP 的可靠传输 - 图1

二、TCP 的确认机制

  • 确认机制(带重传的肯定确认)
    • 接收方收到正确的数据后,向源站回送 ACK 报文
    • 发送方重传错误数据(受损报文、丢失报文)
  • 累计确认
    • ACK number 是接收方希望接收的下一个字节
    • 对 ACK number 以前的所有字节的确认

发送方如何判断错误数据?

  • 没有收到确认

发送方怎么判定没有收到确认?

  • 超时机制

    三、超时重传机制

  • 发送方发送数据时启动一个定时器

    • 定时期间,发送方收到确认后,再发送后续数据
    • 定时期满,发送方重传未确认数据
  • 未确认数据
    • 受损或丢失的数据
    • 确认丢失的数据
  • 重复报文段
    • 原因
      • 重传定时器 < 报文往返时间(Rount Trip Time, RTT
    • 解决
      • 接收方根据报文段的序号,丢弃重复报文段
      • 重传定时器 ≥ RTT -> 自适应超时重传算法
        • 不同的连接传输路径”远近”差异,时延随网络流量变化的差异—固定超时时限只能使 TCP 性能更糟
        • 超时重传报文时,后续的重传报文”再多等一会儿”,这当中也许就收到了确认(考虑时延的不确定性)
    • 关键
      • 精确估计当前的 RTT
  • 失序报文段

    • 原因
      • 封装 TCP 报文段的 IP 数据报的独立选中,不按序到达
    • 解决
      • 接收方对失序报文段不确认,直到收到所有它以前的报文段为止
      • 若确认晚到,发送方重发失序报文段,接收方丢弃重复的报文段

        三、可靠传输协议

        停止等待协议

        理想版(无差错)

        image.png
        上图是最简单的无差错情况,A 发送完之后就暂停发送,等待 B 的确认。B 收到 M1 就向 A 发送了确认。A 收到了 M1 确认分组后再继续发送下一个分组 M2。

        出现错误

        超时重传

        image.png
  • B 端丢弃检验出错的报文。当过了一段时间(RTO)A端重传报文 M1。因此,A 端需要保留已发送分组的副本,用于超时重传。只能收到对应的 ACK 才能清除。

  • RTO 时间就当比 RTT 时间稍长一些。不宜过大,也不能太小。

    • 重传时间设定过短,则会导致不必须的重传,浪费网络资源。
    • 重传时间设定过长,则通信效率就会很低。

      确认丢失

      image.png
  • B 端确认出现丢失,导致A端超时重发 M1。B 端收到重复 M1 分组,直接丢弃,但会重传 ACK。

    确认迟到

    image.png

  • 确认丢失一般发生在网络状况不好的情况,传输过程中并未出现差错,但是 B 对分组 M1 的确认迟到了,A 会收到重复确认,则 A 处理很简单: 收下后就丢弃。

上述这种可靠性传输协议通常称为 自动重传请求 ARQ(Automatic Repeat reQuest)。表示重传的请求是自动进行的。接收方不需要请求发送方重传某个出错的分组。

PAWS,防序列号回绕

PAWS.png

  • Protect Against Wrapped Sequence numbers, PAWS。防序列号回绕。
  • 使用 TCP 时间戳选项解决。接收端可以时间戳看作一个 32 位的扩展序列号,丢失的报文会在时刻 F 重新出现,由于它的时间戳为 2,小于最近的有效时间戳(5或6) ,因此防序列号回绕算法会将其丢弃。

  • 探索停止等待协议信道利用率

    停止等待协议的信道利用率.png
    image.png
    从公式可看出,当 往返时间 RTT 远大于 传输时间 Td,则信道利用率非常低。这还没有考虑差错、重传。

    连续 ARQ 协议

    为了提高传输效率,发送方可以不使用低效率的 停止-等待协议,而是采用 流水线传输
    流水线提供信道利用率.png
    当使用流水线传输时,就要使用 连接 ARQ 协议 和 滑动窗口协议。这里先讲述 ARQ 协议。
    image.png
    连续 ARQ 协议 具有以下特点:

  • 发送方维持着一个一定大小的发送窗口,位于发送窗口内的所有分组都可连续发送出去,而中途不需要等待对方的确认。

  • 接收方一般都采用 累积确认 的方式。即在收到几个分组后对按序达到的最后一个分组发送确认,这表示到这个分组为止的所有分组都已正确收到。
  • 累积确认 优缺点:

    • 优点: 容易实现,即使前面确认丢失也不必全部重传。
    • 缺点: 不能向发送方反映出接收方已经正确收到的所有分组信息。比如发送5个分组,中间第3个分组丢失,这里接收方只能对前两个分组发出确认,而发送方无法知道后三个分组的下落,只能把后面三个分组都再重传一次。就也叫做 回退N(Go-back-N)。
    • 解决办法: SACK。

      滑动窗口

      image.png
  • 窗口内容以 字节 为单位。

  • 滑动窗口分为四个部分,分别是:
    • #1 : 已发送并收到 ACK 确认。由于 TCP 发送端需要保存已发送的数据的副本用做超时重传,但现在既然收到 ACK 确认,后续可以删除这部分数据。
    • #2: 已发送但未收到确认。由于 TCP 采用流水线传输,发送端可以发送此刻窗口内所有分组,并等待 ACK 确认报文。
    • #3: 未发送,但接收端已做好接收这部分数据的准备。如果发送端发送,接收端能接收此部分数据。
    • #4: 未发送,接收端也并未做好这部分数据的准备。如果发送端发送,接收端丢弃并响应一个只在窗口内序号的 ACK。
  • 显然,窗口越大,发送方就可以收到对方确认之前连接发送更多的数据,因而可能获得更高的传输效率。但由于受到当前的网络拥塞程序的制约,发送窗口不能无限增大。

%3CmxGraphModel%3E%
image.png
上图表示发送窗口向右滑动后的情况。

  • 发送端收到4个新的 ACK 确认(即对序号6、7、8、9的确认。由于存在累积确认,所以接收端可能只发送一个 ACK 确认),滑动窗口向右滑动,序号 20~23 的分组现在也可以发送了。
  • 序号 6~9 的分组由于收到 ACK 确认,可以直接删除。

    小结

  • 停止等待协议 + 超时重传 可以保证数据可靠传输,但是信道利用率低得让人头皮发麻。

  • 于是,流水线传输提上日程,也就是 ARQ 协议,发送端可以不用等待 ACK 确认,一次性发送 n 份分组(窗口内数据都可以发送),接收端可以采取 累积确认方式减少网络负载。
  • 但是网络网络复杂多变,上述协议虽说能保证可靠性传输,但是在信道利用率、更低的延迟等指标上还是稍有欠缺。并没有加入流量控制、拥塞控制。
  • 对于流量控制,通过可变的滑动窗口大小解决端到端的流量问题。保证发送端与接收端共享对方的缓存信息(指接收数据的能力)。
  • 对于拥塞控制,现阶段通过 AMID 线性增乘性减策略解决。但是拥塞控制算法还并不完美,也还在不停地进步着。