TCP重传机制
基于超时的重传
原理
发送方发送数据包后,启动一个计时器 (重传定时器),重传间隔为RTO(Retransmission Timeout,RTO)。如果在定时器到期前,没有收到ACK,那就就会假定,数据包丢失,就要重传。RTO是根据RTT(Round-Trip Time,RTT)计算来的,更进一步,其实是基于SRTT(RTT的加权平均值)和RTTVAR(RTT的偏差)计算得到的。RTO是动态变化的,每收到一个ACK或者重传开始后,收到一个ACK或者定期,三种方式来触发更新。其中,为了避免重传时,网络还是有较大的不确定性,一些实现上,也会在重传时,延迟进行RTO的更新。
快速重传
原理
当发送方连续收到3个重复的ACK时,就会立刻重传丢失的那个数据包,不等待超时。之所以一定要收到3个再重传,而不是1个或者2个,这是因为,如果只是偶尔的网络抖动或数据包重排序等暂时性现象,导致接收方没收到包,发送方其实没必要立刻重传。这种机制通过增加重传的触发门槛,提高了对丢包检测的准确性,从而优化了网络资源的利用和数据传输的效率。以下,是它的工作流程示例:
-
发送数据包:
- 发送方发送一系列数据包,如包1, 2, 3, 4。
-
接收方检测丢失:
- 接收方如果只收到数据包1和3,发现数据包2丢失,会发送ACK(1),表示期望收到序列号为2的数据包。
- 此时,ACK(1)是第一个重复的ACK。
-
重复ACK计数:
- 发送方收到第一个重复的ACK(1)时,不立即重传数据包2,而是等待更多的ACK来确认丢失情况。
- 当接收方再次收到数据包3或其他后续数据包时,会继续发送ACK(1),累计到三个重复的ACK(1)。
-
触发快速重传:
- 发送方收到第三个重复的ACK(1)后,确认数据包2确实丢失,立即重传数据包2。
- 发送方继续发送后续数据包,恢复正常传输。
选择性确认(SACK)
原理
升级版的确认机制。接收方回复某个ACK确认包的时候,同时这个数据的TCP可选字段中,还有一个SACK选项,它会分成一个或者多个SACK块,每个块代表我已经收到了什么数据包(通过起始、结束序列号来表示出具体的数据部分)。这样发送方就能明白,原来漏掉了是xx号,接收方已经收到了其他的,那我只要重传xx号的数据包即可。而普通的ACK确认机制,发送方收到要重传某个数据包后,他不知道接收方在此数据包之后的数据包有没有收到,于是干脆把后面的数据包也全部都重传了,这样效率肯定会比SACK低一些。SACK并不是默认开启的,因为它要求客户端、服务器都支持SACK。当前,大多数操作系统,默认都是开启的。是否开启SACK,这会在三次握手的过程中进行确认:
- 如果双方都在SYN包中包含SACK-Permitted选项,则SACK在该连接中被启用;
- 如果任一方不支持或未包含SACK-Permitted选项,则该连接中不会使用SACK。
以下,是它的工作流程示例:
- 发送方发送数据包1、2、3、4、5、6,其中2丢失了; 接收方收到数据包后,发送ACK(1)(表示期望收到的数据段序列号是2)和
- :
- SACK块1:起始序列号3,结束序列号4
- SACK块2:起始序列号5,结束序列号6
- 发送方根据SACK信息,重传数据包2,而不重传3、4、5、6。
本文来自博客园,作者:1234roro 当你迷惘的时候,开始学习吧!当你目标清晰的时候,开始学习吧!转载请注明原文链接:https://www.cnblogs.com/1234roro/p/18305159
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 【杭电多校比赛记录】2025“钉耙编程”中国大学生算法设计春季联赛(1)