TCP的流量控制机制
字数 1905 2025-11-02 13:21:23
TCP的流量控制机制
TCP流量控制是指通过调节发送方的数据发送速率,防止接收方因为处理速度慢或缓冲区不足而导致数据被淹没的机制。其核心是让发送方的发送速率与接收方的处理能力相匹配。
详细讲解:
-
根本问题
- 发送方和接收方通常拥有不同性能的硬件和不同的系统负载。发送方可能以极高的速率生成并发送数据,而接收方的应用程序可能处理数据的速度较慢,或者接收方的网络缓冲区(Buffer)空间有限。
- 如果没有控制机制,发送方持续高速发送的数据包会填满接收方的缓冲区。当缓冲区耗尽后,后续到达的数据包将被接收方直接丢弃,从而引发大量的数据包重传,严重浪费网络资源。
-
解决方案:滑动窗口机制
TCP的流量控制是通过“滑动窗口”机制来完成的。这个窗口的大小决定了在收到接收方的确认(ACK)之前,发送方最多能发送多少字节的数据。窗口大小是动态变化的,由接收方控制。 -
关键数据结构:接收窗口(rwnd)
- 接收方在其TCP缓冲区中维护一个关键概念:接收窗口(Receive Window, rwnd)。
rwnd的大小等于接收方缓冲区当前的空闲空间。- 公式:
接收窗口(rwnd) = 接收方缓冲区总大小 - 已接收但未被应用层读走的数据大小 - 这个
rwnd的值,就是接收方当前愿意接收的数据量上限。
-
运作过程
让我们通过一个具体例子来理解整个过程。假设接收方的总缓冲区大小为4000字节。步骤一:连接建立
- 在TCP三次握手阶段,接收方会将自己的初始接收窗口大小(例如
rwnd = 4000)告知发送方。这意味着发送方可以立即发送最多4000字节的数据。
步骤二:数据传输开始
- 发送方首先发送一个长度为1000字节的数据段(Segment 1)。
- 发送后,发送方等待确认,其可用窗口减小。
步骤三:接收方确认并更新窗口
- 接收方成功收到这1000字节数据,并将其存入缓冲区。此时,接收方缓冲区有1000字节数据等待应用层读取,空闲空间变为
4000 - 1000 = 3000字节。 - 接收方会回复一个ACK报文给发送方。这个ACK报文包含两个关键信息:
- 确认号(Acknowledgment Number):
1001(期望收到的下一个字节的序号,表示前1000字节已成功接收)。 - 新的窗口大小(Window):
3000(即当前的新rwnd)。
- 确认号(Acknowledgment Number):
- 这个ACK报文的意思是:“你发送的前1000字节我已收到,接下来你可以从第1001字节开始,再连续发送最多3000字节的数据。”
步骤四:发送方调整窗口并继续发送
- 发送方收到ACK后,知道前1000字节已经安全送达,于是将发送窗口向前“滑动”。
- 同时,发送方根据ACK报文中通告的新窗口大小(3000)来更新自己的发送窗口。现在它可以发送第1001到第4000字节的数据。
步骤五:处理极端情况 - 零窗口(Zero Window)
- 假设接收方的应用程序处理速度非常慢,一直未从缓冲区读取数据。发送方持续发送,直到将接收方通告的3000字节也全部发送完毕。
- 此时,接收方的缓冲区被完全填满(已接收4000字节,空闲空间为0)。接收方在发送下一个ACK时,会将窗口大小设置为
rwnd = 0。 - 发送方收到这个
rwnd = 0的ACK后,必须停止发送所有数据。此时连接进入“零窗口状态”。
步骤六:打破僵局 - 持续计时器(Persist Timer)
- 当发送方停止发送后,它如何知道接收方的窗口何时不再为零?如果接收方后续发送的包含新窗口大小的ACK报文丢失了,双方将永远等待下去。
- 为了解决这个问题,TCP设置了持续计时器。当发送方收到零窗口通知后,会启动这个计时器。计时器超时时,发送方会发送一个极小的零窗口探测(Zero Window Probe) 报文段(通常只包含1字节数据)。
- 这个探测报文会强制接收方返回一个ACK,其中会包含当前的窗口大小。
- 如果窗口仍为0,发送方则重置持续计时器,继续等待。
- 如果窗口已非零(例如,接收方应用层读取了2000字节数据,
rwnd恢复为2000),那么这个ACK会携带新的窗口大小,发送方收到后就可以立即恢复数据发送。
- 在TCP三次握手阶段,接收方会将自己的初始接收窗口大小(例如
总结:
TCP流量控制的精髓在于接收方主导。接收方通过在每个ACK报文中通告自己的接收窗口(rwnd)大小,来动态地、实时地“指挥”发送方的发送速率。发送方必须严格遵守这个窗口限制,从而确保了数据传输的速率不会超过接收方的处理能力,避免了数据包的丢失和网络资源的浪费。滑动窗口机制使得这个过程非常高效,数据流可以平滑地在网络上传输。