TCP 滑动窗口

学习网址:

介绍

将 TCP 与 UDP 这样的简单传输协议区分开来的根据是它们传输数据的质量。主要考虑的是以下两个关键功能:

  1. 可靠性:保证数据确实到达目的地。如果未到达,能够发现并重传。
  2. 数据流控:管理数据的发送速率,以使接收设备不致于过载。

要完成这些任务,整个协议操作是围绕滑动窗口确认机制来进行的。因此,理解了滑动窗口,也就是理解了TCP。

面向流的滑动窗口确认机制

TCP将独立的字节数据当作流来处理。一次发送一个字节并接收一次确认显然是不可行的。即使重叠传输(即不等待确认就发送下一个数据),速度也还是会非常缓慢。

TCP 消息确认机制如下图所示,首先,每一条消息都有一个识别编号,每一条消息都能够被独立地确认,因此同一时刻可以发送多条信息。设备 B 定期发送给 A 一条发送限制参数,制约设备 A 一次能发送的消息最大数量。设备 B 可以对该参数进行调整,以控制设备 A 的数据流。

../TCP002.jpg

为了提高速度,TCP 并没有按照字节单个发送而是将数据流划分为片段。片段内所有字节都是一起发送和接收的,因此也是一起确认的。确认机制没有采用 message ID 字段,而是使用的片段内最后一个字节的 sequence number。因此一次可以处理不同的字节数,这一数量即为片段内的 sequence number。

发送方和接收方必须就它们将要为数据流中的字节指定的 sequence number 达成一致。这一过程称为同步,在TCP连接建立时完成。

我们可以将 TCP buffer 中的数据分为以下的四类,并把他们看作一个时间轴,如下图所示:

../TCP003.jpg

  1. 已发送已确认:数据流中最早的字节已经发送并得到确认。这些数据是站在发送设备的角度来看的。
  2. 已发送但尚未确认:已发送但尚未得到确认的字节。发送方在确认之前,不认为这些数据已经被处理。
  3. 未发送而接收方已Ready:设备尚未将数据发出,但接收方根据最近一次关于发送方一次要发送多少字节确认自己有足够空间。发送方会立即尝试发送。
  4. 未发送而接收方Not Ready:由于接收方 not ready,还不允许将这部分数据发出。

实际上,收发双方各自维护一套独立的变量,来监控发送和接收的数据流落在哪一类。

发送窗口与可用窗口

概念

整个过程关键的操作在于接收方允许发送方一次能容纳的未确认的字节数。这称为发送窗口,有时也称为窗口。该窗口决定了发送方允许传送的字节数,也是 2 类和 3 类的字节数之和。

$$发送窗口 \cong 窗口, size(窗口) = (已发送但尚未确认字节 + 未发送而接收方已 Ready 字节)$$

最后两类(接收方准备好而尚未发送,接收方未准备好)的分界线在于添加了从第一个未确认字节开始的窗口。如下图所示:

../TCP004.jpg

确认处理以及窗口缩放

过了一段时间,目标设备向发送方传回确认信息。目标设备不会特别列出它已经确认的字节,因为这会导致效率低下。目标设备会发送自上一次成功接收后的最长字节数

当发送设备接收到确认信息,则会将一部分第 2 类字节转移到第 1 类,因为它们已经得到了确认。因为窗口大小没有改变,窗口向右移动确认接收的长度,部分第 4 类字节移动至第 3 类。

处理丢失的信息

TCP 包括一个传输及重传的计时机制。TCP 会重传丢失的片段。但有一个缺陷是:因为它不会对每一个片段分别进行确认,这可能会导致其他实际上已经接收到的片段被重传(比如 42 至 45)。