← 返回题目列表

TCP 的流量控制是怎么实现的?

高频 中等 第 10 / 30 题 更新于 2026/07/28
TCP流量控制滑动窗口

简化版

流量控制解决的是「发送方发太快、接收方来不及处理」的问题。TCP 用滑动窗口实现:接收方在每个 ACK 里带上一个接收窗口(rwnd),告诉发送方「我还能收多少」,发送方的发送量不超过这个窗口。接收方缓冲区快满了就把窗口调小,满了就通告窗口为 0,让发送方暂停。核心是接收方通过窗口控制发送方的速率。

详细版

滑动窗口机制

  • 接收方有一个接收缓冲区,它在 ACK 报文的「窗口大小」字段里通告当前还能接收的字节数(rwnd)。
  • 发送方维护一个发送窗口,大小不超过接收方通告的 rwnd。窗口内的数据可以连续发出、无需逐个等 ACK;收到 ACK 后窗口向前「滑动」,腾出空间发新数据。
  • 接收方处理不过来 → 缓冲区剩余变小 → 通告的 rwnd 变小 → 发送方放慢;缓冲区满 → 通告 rwnd = 0 → 发送方停止发送。

零窗口的处理:当接收方通告窗口为 0,发送方会停下,但它会启动一个持续计时器(persistence timer),定时发送窗口探测报文(ZWP),询问接收方窗口有没有变大。这是为了防止「接收方后来腾出空间、发了个非 0 窗口通告,但这个通告丢了」导致的双方死锁(发送方一直等、接收方以为对方会来)。

完整版教学

一、为什么需要流量控制

发送方和接收方的处理能力可能不匹配:发送方是台高性能服务器,接收方是台手机,或者接收方应用忙着干别的、来不及从缓冲区读数据。如果发送方只管全速发,接收方缓冲区一满,后到的数据只能丢弃,然后触发重传——白白浪费带宽,甚至恶性循环。

流量控制就是让接收方有话语权:由接收方告诉发送方「你最多能发多少」,让发送速率匹配接收方的处理能力。这是一种端到端的、接收方对发送方的「限速」。

二、滑动窗口:不必「发一个等一个」

最朴素的可靠传输是「停等」——发一个包,等它的 ACK,再发下一个。但这样效率极低:一个 RTT 只能传一个包,带宽严重浪费。

滑动窗口的改进是:允许在收到 ACK 之前,连续发送窗口大小的数据。窗口有多大,就能有多少「在途」数据(发出去还没被确认的)。收到 ACK 后窗口向前滑动,继续发新数据。这样一个 RTT 能传一整个窗口的数据,吞吐大幅提升。窗口大小则由接收方的 rwnd(以及拥塞控制的 cwnd)共同决定。

三、零窗口与窗口探测:防死锁

当接收方缓冲区满,它通告 rwnd = 0,发送方停止发送。之后接收方应用读走了数据、腾出空间,会再发一个「非零窗口」的通告告诉发送方可以继续。

问题来了:万一这个「窗口更新」通告丢了呢? 发送方会一直傻等(以为窗口还是 0),接收方也在等发送方发数据——死锁

TCP 的解法是持续计时器 + 窗口探测(Zero Window Probe):发送方收到零窗口后,定时发一个只有 1 字节的探测报文,逼接收方回复一个带最新窗口大小的 ACK。这样即使窗口更新通告丢了,探测也能问出真实窗口,打破死锁。

四、流量控制 vs 拥塞控制

这两个极易混淆,务必分清:

流量控制拥塞控制
防止压垮接收方压垮网络(中间链路)
手段接收窗口 rwnd拥塞窗口 cwnd
谁决定接收方通告发送方根据网络状况估算
范围端到端两点整个网络路径

实际发送窗口取两者的较小值发送窗口 = min(rwnd, cwnd)——既不能撑爆接收方,也不能压垮网络(拥塞控制详见那道题)。

五、常见误区

  • ❌ 把流量控制和拥塞控制混为一谈——一个针对接收方,一个针对网络。
  • ❌ 以为零窗口后发送方就永久卡住——有窗口探测机制打破死锁。
  • ❌ 以为窗口越大越好——太大可能超出接收方或网络承受,实际发送窗口是 rwnd 和 cwnd 的最小值。
  • ❌ 以为滑动窗口只是流量控制——它也是提升吞吐(免去停等)的核心机制。

六、常见误区与追问

考点正确口径
目标防止发送端压垮接收端缓冲区
核心字段TCP 首部窗口大小 rwnd
特殊情况零窗口时通过窗口探测避免死锁
sendWindow = min(cwnd, rwnd)
rwnd = receiver advertised window
rwnd = receiveBufferFreeSpace

流量控制是接收端告诉发送端“我还能接多少”,不是网络告诉发送端“链路还能扛多少”。

  • 误区:流量控制解决网络拥塞。 它解决接收端处理不过来的问题,网络拥塞由拥塞控制处理。
  • 误区:滑动窗口就是发一个等一个。 滑动窗口允许一次发送多个未确认报文,提高管道利用率。
  • 误区:接收窗口为 0 后连接就只能断开。 TCP 有窗口探测机制,定期试探接收端窗口是否恢复。
  • 追问:rwnd 由谁维护? 接收端根据接收缓冲区剩余空间计算,并在 ACK 中通告给发送端。
  • 追问:发送端实际窗口如何决定? 既受接收窗口 rwnd 限制,也受拥塞窗口 cwnd 限制。
  • 追问:窗口扩大因子解决什么? 原始窗口字段 16 位不够大,窗口扩大选项允许高带宽长 RTT 链路充分利用带宽。

七、加强记忆

流量控制防止发送方压垮接收方,靠滑动窗口:接收方在 ACK 里通告接收窗口 rwnd,发送方发送量不超过它,缓冲区满就通告零窗口让发送方暂停,并用窗口探测防止死锁。它和拥塞控制的区别是「防接收方 vs 防网络」,实际发送窗口取 min(rwnd, cwnd)