第23章 TCP:坚持定时器
所属:TCP/IP详解 卷2:实现 来源:TCP/IP详解 卷2:实现
本章描述TCP坚持定时器的实现,包括坚持定时器的作用、工作原理和糊涂窗口综合征的避免等。
23.1 引言
坚持定时器的作用
坚持定时器(Persist Timer):
- 防止零窗口死锁
- 窗口为0时启动
- 周期性探查窗口是否恢复
- 也叫窗口探查定时器
坚持定时器防止零窗口死锁。
什么是零窗口死锁
零窗口死锁(Zero Window Deadlock):
场景:
- 接收方缓冲区满了,通告窗口为0
- 发送方收到,停止发送
- 接收方缓冲区有空间了,发送窗口更新(ACK)
- 这个ACK丢了
- 发送方等接收方发窗口更新
- 接收方等发送方发数据
- 两边都等,死锁了
为什么会死锁:
- ACK是不可靠的
- ACK丢了不会重传
- 发送方不知道窗口恢复了
- 接收方以为发送方收到了
零窗口可能导致死锁。
本章讨论的内容
本章讨论的内容:
- 零窗口问题
- 坚持定时器的工作原理
- 窗口探查
- 糊涂窗口综合征
- 坚持定时器的实现
本章讨论坚持定时器的实现。
23.2 坚持定时器的工作原理
什么时候启动
启动坚持定时器的时机:
- 发送方要发送数据
- 但对端通告的窗口为0
- 不能发送
- 启动坚持定时器
什么时候停止:
- 收到非零窗口的ACK
- 窗口恢复了
- 可以发送了
- 停止定时器
窗口为0就启动,窗口恢复就停止。
坚持定时器的超时时间
超时时间:
- 初始值比较短
- 然后指数退避
- 类似重传定时器
典型值:
- 第一次:5秒
- 第二次:10秒
- 第三次:20秒
- …
- 最大:60秒
为什么指数退避:
- 防止频繁探查
- 减少网络流量
- 给对端恢复的时间
超时时间指数退避。
窗口探查
窗口探查(Window Probe):
- 坚持定时器超时
- 发送一个字节的数据
- 这个字节是窗口外的
- 但可以发,用来试探
探查的特点:
- 只发1字节
- 即使窗口为0也能发
- 对端收到后必须回复ACK
- ACK中包含新的窗口大小
发1字节探查窗口。
窗口探查的结果
窗口探查的可能结果:
-
窗口还是0
- 对端回复ACK,窗口还是0
- 重新启动坚持定时器
- 超时时间更长(指数退避)
-
窗口恢复了
- 对端回复ACK,窗口非0
- 停止坚持定时器
- 可以发送数据了
-
探查丢了
- 没收到ACK
- 定时器超时
- 再发一个探查
- 超时时间更长
探查后根据结果处理。
23.3 糊涂窗口综合征
什么是糊涂窗口综合征
糊涂窗口综合征(Silly Window Syndrome, SWS):
- 窗口很小就发送
- 每个段只有很少的数据
- 效率很低
- 40字节首部 + 1字节数据
- 开销太大
为什么叫糊涂:
- 窗口很小,很傻
- 效率很低
- 不划算
糊涂窗口综合征是小窗口导致的效率问题。
糊涂窗口综合征的原因
原因:
-
接收方的问题
- 缓冲区有一点空间就通告
- 窗口很小
- 发送方就发小的段
-
发送方的问题
- 有一点数据就发
- 不等数据多一点
- 发很多小报文
接收方和发送方都可能导致SWS。
接收方的避免
接收方怎么避免:
- 窗口小就不通告
- 等窗口大一点再通告
- 至少达到一定大小才通告
规则:
- 窗口小于一个MSS就不通告窗口增加
- 或者小于缓冲区的一半
- 等够了再通告
接收方小窗口不通告。
发送方的避免
发送方怎么避免:
- 数据少就不发
- 等数据多一点再发
- Nagle算法就是干这个的
Nagle算法:
- 只有一个未确认的小报文
- 等ACK回来再发下一个
- 或者等数据够一个MSS
发送方用Nagle算法避免。
两边都要避免
两边都要避免:
- 接收方:小窗口不通告
- 发送方:小数据不发送
- 两边一起防止SWS
为什么两边都要:
- 光一边不够
- 两边都防止才保险
- 提高效率
双方共同防止糊涂窗口综合征。
23.4 坚持定时器的实现
定时器的管理
坚持定时器的管理:
- 每个连接一个
- tcpcb中的t_timer[TCPT_PERSIST]
- 单位是500ms的ticks
- 0表示没运行
和其他定时器一起管理。
启动和停止
启动:
- 要发送数据但窗口为0
- 设置定时器初值
- 开始计时
停止:
- 收到非零窗口的ACK
- 定时器设为0
- 停止计时
窗口为0启动,窗口恢复停止。
超时处理
超时处理:
- 发送窗口探查(1字节)
- 计算下一次的超时时间
- 指数退避
- 重新启动定时器
探查的数据:
- 发送窗口外的1字节
- 就是下一个要发的字节
- 即使窗口为0也能发
超时就发探查,然后指数退避。
23.5 坚持定时器和重传定时器的区别
两个定时器的区别
坚持定时器 vs 重传定时器:
| 对比项 | 坚持定时器 | 重传定时器 |
|---|---|---|
| 作用 | 窗口探查 | 超时重传 |
| 触发条件 | 窗口为0 | 有未确认数据 |
| 超时动作 | 发1字节探查 | 重传数据 |
| 目的 | 防止零窗口死锁 | 保证可靠交付 |
| 数据 | 1字节探查 | 重传未确认的 |
两个定时器作用不同。
会不会同时运行
会不会同时运行:
- 可能
- 窗口为0,但还有未确认的数据
- 两个定时器都在跑
优先级:
- 各跑各的
- 互不影响
- 各自超时各自处理
两个定时器可以同时运行。
23.6 小结
坚持定时器概述
-
作用
- 防止零窗口死锁
- 窗口探查
-
为什么需要
- 零窗口可能死锁
- ACK丢了
- 两边都等
工作原理
-
启动停止
- 窗口为0启动
- 窗口恢复停止
-
超时时间
- 指数退避
- 初始短,越来越长
-
窗口探查
- 发1字节
- 试探窗口
- 收到ACK看窗口大小
糊涂窗口综合征
-
什么是SWS
- 小窗口
- 效率低
- 40字节首部+1字节数据
-
原因
- 接收方小窗口通告
- 发送方小数据发送
-
避免
- 接收方:小窗口不通告
- 发送方:Nagle算法
- 两边都防止
实现
-
定时器管理
- tcpcb中的字段
- 500ms单位
- 和其他定时器一起
-
启动停止
- 窗口为0启动
- 窗口恢复停止
-
超时处理
- 发1字节探查
- 指数退避
- 重启定时器
和重传定时器的区别
-
作用不同
- 坚持:窗口探查
- 重传:超时重传
-
可以同时运行
- 互不影响
- 各自处理
关键概念
-
坚持定时器
- 防止零窗口死锁
- 窗口探查
-
零窗口死锁
- ACK丢了
- 两边都等
-
糊涂窗口综合征
- 小窗口效率低
- 两边都要避免
-
窗口探查
- 发1字节
- 试探窗口