# 5.5 TCP流量控制 ## 一、TCP流量控制概述 ### 1.1 什么是流量控制 **流量控制(Flow Control)**: - 控制发送方的发送速率 - 防止接收方缓冲区溢出 - 端到端的控制 ### 1.2 为什么需要流量控制 **问题**: - 发送方发送速度过快 - 接收方处理速度慢 - 接收方缓冲区溢出 - 数据丢失 **解决**: - 接收方告诉发送方自己的接收能力 - 发送方根据接收能力调整发送速率 ### 1.3 流量控制 vs 拥塞控制 | 特性 | 流量控制 | 拥塞控制 | |-----|---------|---------| | 控制对象 | 发送方和接收方 | 发送方和网络 | | 目的 | 防止接收方溢出 | 防止网络过载 | | 范围 | 端到端 | 全局 | | 信息来源 | 接收方通告 | 网络状态 | | 机制 | 滑动窗口 | 拥塞窗口 | --- ## 二、滑动窗口机制 ### 2.1 发送窗口 **发送窗口(Send Window)**: - 发送方可以发送的数据量 - 受接收窗口和拥塞窗口的限制 - 发送窗口 = min(rwnd, cwnd) **发送窗口的组成**: - **已发送并确认**:窗口左侧 - **已发送未确认**:窗口内,等待确认 - **允许发送但未发送**:窗口内,可以发送 - **不允许发送**:窗口右侧 ### 2.2 接收窗口 **接收窗口(Receive Window, rwnd)**: - 接收方缓冲区剩余空间 - 接收方通过ACK报文通告 - 限制发送方的发送量 **接收窗口的计算**: ``` rwnd = 接收缓冲区大小 - 已接收但未确认的数据量 ``` ### 2.3 窗口调整 **接收方**: - 根据缓冲区剩余空间调整rwnd - 在ACK报文中通告rwnd **发送方**: - 根据rwnd调整发送窗口 - 如果rwnd=0,停止发送 --- ## 三、TCP流量控制的工作过程 ### 3.1 正常流量控制 ``` 发送方 接收方 | | |-------- SEQ=1 -------->| | | |<---- ACK=2, rwnd=100 --| | | |-------- SEQ=2 -------->| | | |<---- ACK=3, rwnd=100 --| | | |-------- SEQ=3 -------->| | | |<---- ACK=4, rwnd=50 ---| | | ``` **过程**: 1. 发送方发送数据 2. 接收方接收数据,处理 3. 接收方发送ACK,通告rwnd 4. 发送方根据rwnd调整发送窗口 ### 3.2 窗口减小 ``` 发送方 接收方 | | |-------- SEQ=1 -------->| | | |<---- ACK=2, rwnd=100 --| | | |-------- SEQ=2 -------->| | | |-------- SEQ=3 -------->| | | |-------- SEQ=4 -------->| | | |<---- ACK=2, rwnd=50 ---| (缓冲区快满) | | |-------- SEQ=5 -------->| | | |<---- ACK=2, rwnd=20 ---| (缓冲区快满) | | |-------- SEQ=6 -------->| | | |<---- ACK=2, rwnd=0 ----| (缓冲区满) | | ``` **过程**: 1. 接收方缓冲区快满,减小rwnd 2. 发送方减小发送窗口 3. 接收方缓冲区满,rwnd=0 4. 发送方停止发送 --- ## 四、零窗口问题 ### 4.1 什么是零窗口 **零窗口**: - rwnd = 0 - 接收方缓冲区满 - 发送方停止发送 ### 4.2 零窗口的问题 **问题**: - 接收方处理完数据,恢复rwnd - 接收方发送窗口更新报文 - 窗口更新报文丢失 - 发送方一直等待 - 双方死锁 ### 4.3 持续计时器 **持续计时器(Persistence Timer)**: - 解决零窗口死锁问题 - 发送方收到rwnd=0后,启动持续计时器 - 超时后发送窗口探测报文 **窗口探测报文**: - 1字节的数据 - 接收方必须响应 - 携带新的rwnd **过程**: 1. 发送方收到rwnd=0 2. 启动持续计时器 3. 超时后发送窗口探测报文 4. 接收方响应,通告新的rwnd 5. 如果rwnd>0,恢复发送 6. 如果rwnd=0,重启持续计时器 ### 4.4 持续计时器的设置 **初始值**: - 通常设置为RTO **超时后**: - 指数退避 - 最大到60秒 --- ## 五、糊涂窗口综合征 ### 5.1 什么是糊涂窗口综合征 **糊涂窗口综合征(Silly Window Syndrome)**: - 接收方通告很小的窗口 - 发送方发送很小的数据 - 效率低下 - 开销大 ### 5.2 产生原因 **接收方**: - 应用程序每次只读取很少的数据 - 缓冲区空间缓慢释放 - 通告很小的rwnd **发送方**: - 收到很小的rwnd - 发送很小的数据 ### 5.3 解决方法 **接收方(Clark算法)**: - 不通告很小的窗口 - 等到缓冲区有足够的空间 - 或者等到缓冲区半空 **发送方(Nagle算法)**: - 如果数据很小,等待 - 等到有足够的数据 - 或者收到上一个数据的ACK **Nagle算法**: 1. 如果数据量 ≥ MSS,立即发送 2. 如果之前有数据未确认,等待 3. 如果之前的数据已确认,立即发送 --- ## 六、TCP流量控制的示例 ### 6.1 正常流量控制 ``` 发送方 接收方 | | |-------- SEQ=1 -------->| | | |<---- ACK=2, rwnd=100 --| | | |-------- SEQ=2 -------->| |-------- SEQ=3 -------->| |-------- SEQ=4 -------->| | | |<---- ACK=5, rwnd=100 --| | | |-------- SEQ=5 -------->| |-------- SEQ=6 -------->| | | |<---- ACK=7, rwnd=100 --| | | ``` ### 6.2 零窗口处理 ``` 发送方 接收方 | | |-------- SEQ=1 -------->| | | |<---- ACK=2, rwnd=0 ----| | | | (停止发送) | | | |-------- 窗口探测 ------>| | | |<---- ACK=2, rwnd=0 ----| | | | (持续计时器超时) | | | |-------- 窗口探测 ------>| | | |<---- ACK=2, rwnd=50 ----| | | | (恢复发送) | |-------- SEQ=2 -------->| | | ``` --- ## 七、考研重点 1. **流量控制的概念**: - 什么是流量控制 - 为什么需要流量控制 - 流量控制 vs 拥塞控制 2. **滑动窗口机制**: - 发送窗口 - 接收窗口(rwnd) - 窗口调整 3. **TCP流量控制的工作过程** 4. **零窗口问题**: - 什么是零窗口 - 零窗口的问题 - 持续计时器 5. **糊涂窗口综合征**: - 什么是糊涂窗口综合征 - 产生原因 - 解决方法(Clark算法、Nagle算法) 6. **TCP流量控制的示例** --- *下一节:5.6 TCP拥塞控制*