第18章 TCP:重传
所属:TCP/IP详解 卷2:实现 来源:TCP/IP详解 卷2:实现
本章描述TCP重传的实现,包括重传定时器、重传策略、快速重传和拥塞控制等。
18.1 引言
重传的作用
重传的作用:
- 保证数据可靠交付
- 丢了的数据要重发
- TCP可靠性的核心
- 处理网络丢包
重传是TCP可靠性的基础。
什么时候需要重传
需要重传的情况:
-
超时重传
- 重传定时器超时
- 没收到ACK
- 认为丢了
-
快速重传
- 收到多个重复ACK
- 推断某个段丢了
- 提前重传,不等超时
两种重传方式:超时重传和快速重传。
本章讨论的内容
本章讨论的内容:
- 重传定时器
- 超时重传
- 快速重传
- 重传的策略
- 拥塞控制与重传的关系
本章详细讨论TCP的重传机制。
18.2 重传定时器
重传定时器的启动
重传定时器的启动:
- 发送数据时启动
- 如果定时器已经在运行,就不重启
- 只有最早的未确认段超时才重传
为什么不每次都重启:
- 定时器是针对最早的未确认段
- 每次发新数据不重启
- 保证最早的能及时超时
定时器针对最早的未确认段。
重传定时器的停止
重传定时器的停止:
- 所有数据都被确认了
- 没有未确认的数据
- 定时器设为0
部分确认:
- 收到ACK,确认了一部分
- 还有未确认的
- 定时器继续运行
- 不重启
都确认了才停止。
RTO的计算
RTO(Retransmission TimeOut):
- 根据RTT动态计算
- SRTT + 4 × RTTVAR
- 有最小和最大限制
- 典型值:1秒到64秒
为什么有最小和最大:
- 最小:防止RTO太小,不必要的重传
- 最大:防止RTO太大,恢复太慢
RTO动态调整,有上下限。
18.3 超时重传
超时重传的过程
超时重传的处理步骤:
-
重传最早的段
- 重传未确认的第一个段
- 不是所有未确认的
-
调整拥塞窗口
- 慢启动阈值设为当前窗口的一半
- 拥塞窗口设为1个MSS
- 进入慢启动
-
指数退避
- RTO翻倍
- 下次超时时间更长
- 最多到上限
-
重启定时器
- 用新的RTO重启
- 等待ACK
超时后重传,调整拥塞参数。
重传一个还是多个
重传一个还是多个?
- 经典实现:只重传最早的一个
- 因为不知道丢了多少
- 先重传一个,看情况
- 后面的可能没丢
为什么不都重传:
- 可能只丢了一个
- 都重传浪费带宽
- 可能加剧拥塞
超时只重传最早的一个。
指数退避
指数退避(exponential backoff):
- 第一次超时:RTO
- 第二次:2×RTO
- 第三次:4×RTO
- 第四次:8×RTO
- …
- 直到上限(如64秒)
为什么要退避:
- 网络可能拥塞
- 重传太频繁会更拥塞
- 退避给网络恢复的时间
指数退避避免加剧拥塞。
18.4 快速重传
什么是快速重传
快速重传(Fast Retransmit):
- 收到重复ACK时触发
- 不用等超时
- 更快地重传丢失的段
- 提高性能
为什么叫快速:
- 比超时重传快
- 超时可能要等几秒
- 快速重传几个RTT就触发
快速重传比超时重传快。
快速重传的原理
快速重传的原理:
-
收到乱序的段
- 比如收到第1、2、4、5段
- 第3段丢了
- 收到4、5时,ACK还是2
-
发送方收到重复ACK
- 收到多个相同的ACK
- 说明后面的段收到了
- 中间的丢了
-
推断丢包
- 收到3个重复ACK
- 认为那个段丢了
- 立即重传
- 不用等超时
重复ACK说明中间有段丢了。
为什么是3个重复ACK
为什么是3个重复ACK?
- 1个:可能是乱序
- 2个:可能是乱序
- 3个:很可能是丢了
- 阈值设为3
乱序和丢包的区别:
- 乱序:可能1-2个重复ACK
- 丢包:更多重复ACK
- 3个是经验值
3个重复ACK是阈值。
快速重传的处理
快速重传的处理步骤:
-
收到第3个重复ACK
- 推断丢了
- 立即重传丢失的段
-
调整拥塞窗口
- 慢启动阈值减半
- 拥塞窗口 = ssthresh + 3×MSS
- 进入快速恢复
-
不重启重传定时器
- 因为只是快速重传
- 定时器还在跑
- 如果还是超时,再按超时处理
快速重传不用等超时。
18.5 快速恢复
什么是快速恢复
快速恢复(Fast Recovery):
- 快速重传之后
- 不进入慢启动
- 用拥塞避免
- 更快恢复
为什么需要:
- 快速重传说明网络还能用
- 只是丢了一个包
- 不用太保守
- 快速恢复性能更好
快速恢复配合快速重传。
快速恢复的过程
快速恢复的步骤:
-
收到3个重复ACK
- ssthresh = cwnd / 2
- cwnd = ssthresh + 3×MSS
- 重传丢失的段
-
继续收到重复ACK
- cwnd += 1 MSS
- 如果可以,发送新数据
-
收到新的ACK
- cwnd = ssthresh
- 进入拥塞避免
- 恢复正常
快速恢复避免了慢启动的慢。
18.6 拥塞控制
拥塞控制概述
拥塞控制(Congestion Control):
- 防止网络拥塞
- 调整发送速率
- 四个阶段:
- 慢启动
- 拥塞避免
- 快速重传
- 快速恢复
拥塞控制防止网络过载。
慢启动
慢启动(Slow Start):
- 开始时慢慢增加
- 每收到一个ACK,cwnd加1 MSS
- 指数增长
- 直到达到ssthresh
为什么叫慢启动:
- 比一开始就发很多慢
- 但实际上是指数增长,很快
- 只是相对于突然发送而言
慢启动是指数增长。
拥塞避免
拥塞避免(Congestion Avoidance):
- cwnd超过ssthresh后
- 每个RTT加1 MSS
- 线性增长
- 增长比慢启动慢
为什么:
- 接近拥塞点了
- 要小心
- 线性增长更安全
拥塞避免是线性增长。
拥塞控制的状态转换
拥塞控制的状态转换:
开始
|
v
慢启动 <----+
| |
v |
达到ssthresh | 超时
| |
v |
拥塞避免 ----+
|
| 3个重复ACK
v
快速重传+快速恢复
|
v
拥塞避免
不同事件触发不同的状态转换。
18.7 重传的其他问题
重传歧义
重传歧义(retransmission ambiguity):
- 重传后收到ACK
- 不知道是对第一次的还是重传的ACK
- RTT测量会有问题
解决方法:
- Karn算法
- 重传的段不用于RTT测量
- 避免歧义
Karn算法解决重传歧义。
重传的次数限制
重传次数限制:
- 不能无限重传
- 有最大次数限制
- 超过就认为连接断了
- 复位连接
典型值:
- 数据段:15次左右
- SYN:3次左右
- 不同实现可能不同
重传有次数限制。
18.8 小结
重传概述
-
作用
- 保证可靠交付
- 处理丢包
-
两种方式
- 超时重传
- 快速重传
重传定时器
-
启动停止
- 有未确认数据就启动
- 都确认了就停止
-
RTO计算
- 根据RTT动态计算
- SRTT + 4×RTTVAR
- 有上下限
超时重传
-
过程
- 重传最早的段
- 调整拥塞窗口
- 指数退避
- 重启定时器
-
指数退避
- 每次超时RTO翻倍
- 防止加剧拥塞
快速重传
-
原理
- 重复ACK触发
- 不用等超时
- 更快恢复
-
阈值
- 3个重复ACK
- 区分乱序和丢包
-
处理
- 立即重传
- 调整拥塞参数
快速恢复
-
作用
- 配合快速重传
- 不进入慢启动
- 更快恢复
-
过程
- ssthresh减半
- cwnd = ssthresh + 3MSS
- 收到新ACK回到拥塞避免
拥塞控制
-
四个阶段
- 慢启动:指数增长
- 拥塞避免:线性增长
- 快速重传:重复ACK触发
- 快速恢复:快速恢复
-
状态转换
- 超时 → 慢启动
- 3个重复ACK → 快速恢复
其他问题
-
重传歧义
- Karn算法解决
-
次数限制
- 不能无限重传
- 超过就断开
关键概念
-
超时重传
- 定时器超时
- 指数退避
-
快速重传
- 重复ACK触发
- 比超时快
-
快速恢复
- 配合快速重传
- 避免慢启动
-
拥塞控制
- 慢启动
- 拥塞避免
- 调整发送速率