TCP 流量控制 — 接收窗口 rwnd 动态调整

初始A 连续发送,填满发送窗口

B 初始通告 rwnd=400。A 设 swnd=400,连续发送:

A 发送seq=1, DATA 1-100可用窗口
seq=1, 100B300
seq=101, 100B200
seq=201, 100B100

每次发送后可用窗口减少。窗口仍是 400,但"已发未确认"字节从 0 → 300。

/* 发送窗口状态 */
swnd = 400;
/* 已发送 1-300,未确认 */
/* P1=1, P2=301, P3=401 */
inflight = 300;  // 已发未确认
usable   = 100;  // 还可发送

第一次流量控制rwnd 从 400 → 300

B 的应用程序读取速度慢,接收缓存可用空间从 400 降到 300。B 在 ACK 中通告新的 rwnd=300

B → A:ACK=201, rwnd=300
含义201 之前的数据已收到;接收窗口缩小为 300
A 的发送窗口变化
swnd400 → 300窗口收缩 → 覆盖 201–500
201-300已发未确认暂留在发送缓存中
301-500允许发送可用窗口 = 200
/* A 收到 ACK=201, rwnd=300 后 */
P1 = 201;  // 后沿前移:1-200 已确认可删除
P2 = 301;  // 201-300 已发未确认
P3 = 501;  // 前沿 = 201+300=501

swnd    = P3 - P1 = 300;  // 窗口缩小!
inflight = P2 - P1 = 100;
usable   = P3 - P2 = 200;

窗口用完发送 301-500 → 可用窗口归零

A 将窗口内剩余数据发出:

A 发送seq=301, DATA 301-400可用窗口 = 100
A 发送seq=401, DATA 401-500可用窗口 = 0

可用窗口归零 → A 不能再发送新数据。

此时 P₁=201, P₂=501, P₃=501。inflight=300, usable=0。

如果迟迟收不到 ACK,已发送的数据(201-300, 301-400, 401-500)将等待超时重传。

/* 窗口用完 */
P1 = 201; P2 = 501; P3 = 501;
inflight = 300; usable = 0;

/* A 暂停发送,等待 ACK */
/* 如果 201-300 超时 → 重传 */
/* 如果 B 的 ACK 到达 → 窗口滑动 */

第二、三次流量控制rwnd → 100 → 0

A 重传 201-300。B 收到后回复 ACK,但 B 的缓存持续堆积:

阶段B 通告A 响应
第二次流量控制ACK=501, rwnd=100swnd→100,覆盖 501-600
A 发送seq=501, 100B → 可用窗口归零
第三次流量控制ACK=601, rwnd=0swnd→0,停止发送

B 的缓存已满,应用进程读取过慢 → rwnd 从 300 → 100 → 0。

A 三次被迫收缩发送窗口:接收方掌握绝对控制权

/* 流量控制的核心逻辑 */
/* rwnd 由接收方决定,发送方被动执行 */

// B 应用读得慢 → 缓存满 → rwnd↓
// B 应用读得快 → 缓存空 → rwnd↑
// rwnd=0 → A 停止发送
// A 不主动决定窗口大小

/* 这就是"流量控制":
   接收方直接反馈 → 发送方被动适应 */