TCP 协议作为一个可靠的面向流的传输协议,其可靠传输与流量控制由滑动窗口协议保证,而拥塞控制则由拥塞窗口结合一系列的控制算法实现。
滑动窗口协议
关于这部分自己不晓得怎么叙述才好,因为理解的部分更多,下面就用自己的理解来介绍下 TCP 的精髓:滑动窗口协议。
所谓滑动窗口协议,自己理解有两点:
- 「窗口」对应的是一段可以被发送者发送的字节序列,其连续的范围称之为「窗口」;
- 「滑动」则是指这段「允许发送的范围」是可以随着发送的过程而变化的,方式就是按顺序「滑动」。
在引入一个例子来说这个协议之前,我觉得很有必要先了解以下前提:
- TCP 协议的两端分别为发送者 A 和接收者 B,由于是全双工协议,因此 A 和 B 应该分别维护着一个独立的发送缓冲区和接收缓冲区,由于对等性(A 发 B 收和 B 发 A 收),我们以 A 发送 B 接收的情况作为例子;
- 发送窗口是发送缓存中的一部分,是可以被 TCP 协议发送的那部分,其实应用层需要发送的所有数据都被放进了发送者的发送缓冲区;
- 发送窗口中相关的有四个概念:
- 已发送并收到确认的数据(不再处于发送窗口和发送缓冲区之内)
- 已发送但未收到确认的数据(位于发送窗口之中)
- 允许发送但尚未发送的数据
- 发送窗口外发送缓冲区内暂时不允许发送的数据
- 每次成功发送数据之后,发送窗口就会在发送缓冲区中按顺序移动,将新的数据包含到窗口中准备发送;
TCP 建立连接的初始,B 会告诉 A 自己的接收窗口大小,比如为「20」。对照下图:此时 B 已经确认到 30 号字节,期望收到的序号是 31,于是 A 构造出自己的发送窗口 3150(后沿 31、前沿 51),3150 是允许发送的序号,51 及以后暂时不允许发送:

A 一口气发送了 11 个字节(序号 3141)。由于最先的 31 号字节还没有得到 B 的确认,A 的发送窗口位置保持不变,可用窗口是 4250;而 B 这一侧,接收到的字节里有些没有按序到达,这些乱序的字节只能先暂存在接收窗口里等缺口补齐,B 的确认号仍然停在 31(B 期望收到的序号):

只有当 A 成功发送了数据,即发送的数据得到了 B 的确认之后,才会移动滑动窗口离开已发送的数据;同时 B 则确认连续的数据分组,对于乱序的分组则先接收下来,避免 A 因收不到确认而重传、给网络徒增重复的分组。下图的上半部分就是缺口补齐后的场景:B 连续确认,A 收到新的确认号,发送窗口整体向前滑动,可用窗口增大;而下半部分则是另一种情形——窗口内允许发送的字节已经全部发出但都没被确认,可用窗口收缩为 0,A 必须停下来等确认,收到新的确认后窗口才能继续前移:

滑动窗口的指针计算、流量控制与拥塞控制的完整论述(慢启动、拥塞避免、拥塞发生、快速恢复),可以继续看《TCP 重传、滑动窗口、流量控制与拥塞控制》。