1.流量控制
TCP 流量控制(Flow Control) 的核心目标是:防止发送方发得太快,导致接收方缓冲区溢出而丢包。
它就像是一个"水坝调节系统",确保上游(发送端)的水流速度永远不会超过下游(接收端)水库的承载能力。
1. 核心机制:滑动窗口 (Sliding Window)
TCP 利用 滑动窗口 来实现流量控制。在 TCP 报文首部中,有一个专门的字段叫 Window (窗口大小)。
-
接收方 :在每次给发送方回 ACK(确认报文)时,会通过这个字段告诉发送方:"我现在的接收缓冲区还能装下多少字节的数据。" 这个值被称为 RWND (Receive Window)。
-
发送方:根据接收方的 RWND 值来调整自己的发送速度,确保"已发送但未确认"的数据量永远不超过 RWND。
2. 流量控制的过程演示
假设 A 是发送端,B 是接收端,初始窗口大小为 400 字节:
-
数据传输:A 发送了 400 字节数据给 B。
-
缓冲区变满:B 处理数据较慢,只处理了 100 字节,缓冲区还剩 0 字节空间。
-
窗口通告 :B 向 A 发送 ACK,并将
Window字段设为 0。 -
发送暂停 :A 收到
Window=0的报文后,停止发送数据。此时,A 进入等待状态。
3. 零窗口死锁与坚持定时器 (Persist Timer)
如果 B 后来处理完了数据,腾出了空间,并发送了一个 Window=500 的报文通知 A,但这个报文在网络中丢失了,就会发生死锁:
-
A 在等 B 的通知。
-
B 在等 A 发数据。
解决方法 : TCP 为发送方设计了 坚持定时器 (Persist Timer)。
-
当发送方收到
Window=0时,启动定时器。 -
定时器到期后,发送方发送一个极小的 零窗口探测报文 (Zero Window Probe)。
-
接收方在确认这个探测报文时,必须给出当前的窗口大小。如果还是 0,重设计时器;如果大于 0,死锁解除。
4. 传输效率优化
在流量控制中,有两个经典问题会影响性能:
-
糊涂窗口综合症 (Silly Window Syndrome): 如果接收方处理很慢,每次只腾出几个字节的空间就通知发送方,而发送方也真的只发几个字节。这会导致网络中充斥着大量只有几个字节负载的 TCP 包(头部开销太大,效率极低)。
-
解决方案:
-
接收方策略:除非缓冲区有足够大的空间(比如达到总容量的一半或一个最大报文段 MSS),否则不通告更新窗口。
-
发送方策略 (Nagle 算法):积累足够多的数据,或者等到收到前一个包的 ACK 后再发送。
-
2.拥塞控制
如果说流量控制是发送方与接收方之间的"点对点"协调,那么**拥塞控制(Congestion Control)**就是针对整个互联网"交通状况"的宏观调控。它的目的是防止过多的数据注入到网络中,避免路由器或链路过载。
TCP 主要通过一个动态维护的**拥塞窗口(CWND, Congestion Window)**来实现这一功能。
拥塞控制的四大核心算法
TCP 的拥塞控制是一个从"试探"到"碰撞"再到"调整"的过程,主要包含以下四个阶段:
1. 慢开始 (Slow Start)
-
逻辑 :刚开始发送数据时,由于不清楚网络状况,发送方会从小到大指数级增加
CWND。 -
过程:从 1 个 MSS(最大报文段)开始,每收到一个 ACK,窗口翻倍(1 -> 2 -> 4 -> 8...)。
-
目的:迅速试探出网络的承载能力。
2. 拥塞避免 (Congestion Avoidance)
-
触发点 :当
CWND达到一个预设的阈值(ssthresh,慢开始门限)时。 -
逻辑 :为了防止增长过快导致网络瞬间拥堵,从指数增长改为线性增长。
-
过程:每个轮次(RTT)只增加 1 个 MSS。
3. 快重传 (Fast Retransmit)
-
逻辑 :如果接收方收到了一个失序的报文段,会立即发送重复确认。
-
触发点 :发送方如果连续收到 3 个重复的 ACK,就认为该包已丢失,不需要等待超时定时器(RTO)到期,直接立即重传。
-
目的:缩短等待时间,保持数据流的连续性。
4. 快恢复 (Fast Recovery)
-
逻辑:既然能收到 3 个重复 ACK,说明网络虽然丢了包,但还能传数据(没彻底瘫痪)。
-
操作:
-
将
ssthresh减半。 -
将
CWND设置为新的ssthresh大小(有的实现是加 3 个 MSS)。 -
直接进入拥塞避免阶段,而不是回到"慢开始"。
-
⚠️ 当"真拥塞"发生时(超时)
如果网络状况极差,导致发送方出现了 超时(Timeout) 而不是收到重复 ACK:
-
ssthresh变为当前窗口的一半。 -
CWND直接重置为 1。 -
重新开始 慢开始 过程。
这是一种最严厉的惩罚机制,旨在让出带宽让网络"喘口气"。
📊 总结对比:CWND 的变化
| 状态 | 窗口增长速度 | 触发切换条件 |
|---|---|---|
| 慢开始 | 指数增长 (2\^n) | CWND >= ssthresh -> 进拥塞避免 |
| 拥塞避免 | 线性增长 (+1) | 丢包/超时 -> 触发惩罚 |
| 快恢复 | 减半后线性增长 | 收到新的有效 ACK -> 恢复正常 |
3.OSI 七层参考模型
OSI 模型是理论上的"教科书"标准,而 TCP/IP 是互联网实际运行的"事实"标准。
🏗️ OSI 七层参考模型
OSI(Open System Interconnection)由国际标准化组织 ISO 提出,从上到下依次为:
| 层级 | 名称 | 功能简述 | 协议/设备示例 |
|---|---|---|---|
| 7 | 应用层 (Application) | 为应用程序提供服务。 | HTTP, FTP, SMTP, DNS |
| 6 | 表示层 (Presentation) | 数据格式化、加密、解密、压缩。 | SSL/TLS, JSON, JPEG |
| 5 | 会话层 (Session) | 建立、管理和终止会话(管理同步点)。 | RPC, NetBIOS |
| 4 | 传输层 (Transport) | 提供端到端的逻辑通信、流量控制、拥塞控制。 | TCP, UDP |
| 3 | 网络层 (Network) | 路由选择、逻辑地址寻址(跨网络通信)。 | IP, ICMP, 路由器 |
| 2 | 数据链路层 (Data Link) | 帧同步、物理地址 (MAC) 寻址、差错校验。 | 以太网, ARP, 交换机 |
| 1 | 物理层 (Physical) | 透明传输比特流(电信号、光信号)。 | 网线, 光纤, 中继器 |
🛠️ TCP/IP 四层 vs 五层模型
在实际开发(如 Java 后端或 Flutter 网络编程)中,我们更多参考 TCP/IP 结构。
-
TCP/IP 四层(标准):应用层、传输层、网际层、网络接口层。
-
TCP/IP 五层(教学常用):它是把 OSI 的上三层合并为"应用层",下两层保留。
对应关系:
-
应用层:对应 OSI 的应用层、表示层、会话层。
- 你的代码逻辑、JSON 解析、SSL 加密都在这一层。
-
传输层:对应 OSI 传输层(TCP/UDP)。
- 负责你之前问的滑动窗口、拥塞控制。
-
网络层:对应 OSI 网络层(IP 协议)。
- 负责数据包在公网上的跳跃。
-
数据链路层 & 物理层:对应网络接口层。
- 处理网卡 MAC 地址和二进制比特流。
🔄 数据封装与拆解过程
当你发送一个请求时(例如使用 LangChain4j 发送一个提示词):
-
应用层:构造 HTTP 请求。
-
传输层 :打上 TCP 头部 (包含端口号、序列号,用于流量控制)。
-
网络层 :打上 IP 头部(包含源/目的 IP 地址,用于路由)。
-
链路层 :打上 以太网帧头(包含 MAC 地址)。