TCP 重传机制:数据丢了、ACK 丢了,为什么还能补回来
围绕TCP 重传机制章节,讲清序号、确认号、发送缓冲区、RTO 超时重传、重复 ACK、快速重传和快速恢复。
相关工具
可靠不是不丢,而是能发现并补上
很多人说 TCP 可靠,容易误解成“TCP 传输过程中不会丢包”。真实网络里,数据段可能丢失,ACK 也可能丢失,路由器队列可能溢出,链路也可能抖动。TCP 的可靠性,不是保证问题不发生,而是尽量发现问题,并把缺失的数据补回来。
资料 在 TCP 重传机制里说,当发送方的数据在传输过程中丢失、损坏或延迟,接收方可以请求发送方重新传输这些数据。实现这个能力,离不开序号、确认号、发送窗口、接收窗口、定时器和重传策略。
先记住一句话:TCP 传的是有序字节流。每个字节都有位置,接收方通过确认号告诉发送方“我已经连续收到哪里了,下一段从哪里开始发给我”。只要这个坐标系在,TCP 就能判断哪些数据已确认、哪些数据可能丢了、哪些数据需要重新发送。
序号和确认号是重传的基础
已有内容提到,在 TCP 通信中,每个发送的字节都有唯一序号,每个接收的字节都有确认号。比如发送方发出一段数据,序号从 1001 开始,长度 1000 字节,那么接收方完整收到后,可以返回 `ACK=2001`,意思是 2001 之前的字节我都连续收到了。
这里的确认号不是简单说“收到这个包”,而是说“下一个期望收到的字节序号”。这让 TCP 可以处理乱序、重复和丢失。收到重复数据时,接收方可以根据序号判断它已经处理过,不会把同一段字节重复交给上层。
发送方也会把未确认的数据保留在发送缓冲区里。数据发出后不能马上丢掉,因为还没确认它真的到达。如果超时没有收到 ACK,或者收到重复 ACK 暗示中间缺了一段,发送方就从缓冲区里取出对应数据重新发送。
超时重传:等不到 ACK 就补发
资料 对超时检测的描述是:发送方为每个发送的数据段设置一个定时器,定时器时长称为超时时间。如果在超时时间内没有收到确认,发送方会认为数据丢失或损坏,触发重传。
最直观的情况是数据段丢了。发送方发出一段数据,网络中间把它弄丢了,接收方根本没收到,自然不会返回对应 ACK。发送方等到重传超时时间 RTO 到了,还没拿到确认,就重新发送同一段数据。
另一种情况是数据到了,但 ACK 丢了。接收方其实已经收到数据,也返回了 ACK,只是 ACK 在路上丢了。发送方看不到 ACK,也会超时重传。接收方再次收到这段相同序号的数据后,会识别为重复数据,丢弃重复内容,再返回 ACK。这就是为什么 TCP 重传不等于业务重复处理。

发送方为未确认数据启动 RTO 定时器。数据段丢失或 ACK 丢失时,发送方等不到确认会重传,接收方通过序号去重。
RTO 不能太短,也不能太长
超时重传听起来简单,但 RTO 设置很讲究。太短会误判。网络只是稍微慢一点,ACK 还在路上,发送方就提前重传,造成额外流量。太长又会恢复太慢,数据真丢了也要等很久,用户看到的就是卡顿。
实际 TCP 会根据往返时间 RTT 的估计动态调整 RTO。路径延迟稳定时,RTO 可以相对贴近真实 RTT;路径抖动大时,RTO 要留出余量,避免频繁误重传。我们不需要在应用层手动算这些,但排查网络问题时要知道:超时重传往往意味着 ACK 在合理等待时间内没有回来。
如果抓包里看到大量 Retransmission,不一定马上说明源站坏了。它可能是链路丢包,可能是跨地域 RTT 抖动,也可能是接收端迟迟不确认。要结合 RTT、窗口大小、重复 ACK 和网络路径一起看。
重复 ACK:接收方在说我还缺这一段
超时重传要等定时器,有时太慢。文中提到快速重传策略:当接收方连续接收到相同确认号时,它会立即向发送方发送冗余确认,以触发发送方进行重传。
举个例子,发送方连续发出 Seq=1、2、3、4、5,其中 Seq=2 丢了,Seq=3、4、5 都到了。接收方已经收到 1,所以会确认 ACK=2,表示下一段想要 2。后来 3、4、5 虽然到了,但中间缺了 2,接收方不能按序交付,只能继续返回 ACK=2。
发送方连续看到多个 ACK=2,就能推断:接收方不是没收到任何数据,而是一直在等 2。于是发送方不必等 RTO 超时,直接重传 Seq=2。这就是快速重传。
快速重传比超时重传更早发现丢包
快速重传的好处,是把等待时间缩短了。只要后续数据还能到达接收方,接收方就会不断反馈重复 ACK。发送方从这些重复 ACK 里看到缺口,能更早补上丢失的数据段。
这也说明快速重传依赖一个前提:丢的不是最后一段,后面还有数据到达接收方。如果发送方只发了一段数据,它丢了,接收方没有任何后续数据可触发重复 ACK,发送方还是只能等超时。
因此,超时重传和快速重传不是谁替代谁。超时重传是兜底,快速重传是更快的发现方式。网络状况不同、丢包位置不同,触发路径也会不同。

当中间某段丢失但后续数据到达时,接收方会重复确认缺失序号。发送方收到多个重复 ACK 后,不等超时就重传缺失段。
快速恢复会配合重传一起降速
资料 在快速重传后还提到快速恢复。发送方接收到快速重传的确认后,不需要等到超时再次发送,而是可以使用快速恢复算法继续发送未丢失的数据。它和拥塞控制联系很紧。
因为丢包通常意味着网络可能拥塞,发送方不能补发完丢失段后继续按原速度猛发。快速恢复会把拥塞窗口降下来,但不会像超时那样完全退回到最小窗口。原因是重复 ACK 说明网络还在传输后续数据,情况没有超时那么严重。
所以一条 TCP 连接遇到丢包后,既要把缺失的数据补上,也要把发送节奏调低一点。重传解决可靠性,快速恢复解决恢复过程中的拥塞控制。
重传策略不是简单全量重发
文中说,如果只有一个数据段丢失,发送方只会重传丢失的数据段;如果多个数据段丢失,发送方可能会使用更复杂的算法决定哪些数据需要重传。这一点很重要。
TCP 不会因为一个字节丢了,就把整个文件从头再发。它根据序号、确认号和接收方反馈定位缺失范围。确认过的数据不用再发,未确认或被判断丢失的数据才需要重传。这样才能在保证可靠的同时,尽量减少重复流量。
实际协议栈还可能使用选择性确认 SACK 等机制,让接收方告诉发送方哪些不连续的数据块已经收到。这样发送方能更准确地补缺口。即使不展开这些细节,也要理解方向:TCP 的重传是按字节序号和确认状态精细处理的。
重传不等于应用层幂等
这里有个工程上很容易混的问题:TCP 重传和业务重试不是一回事。TCP 重传发生在传输层,重发的是相同字节流里的某一段。接收方 TCP 栈会根据序号去重,保证上层应用按顺序看到一份数据。
业务重试发生在应用层。比如客户端超时后又发了一次下单请求,服务端可能真的收到两次完整 HTTP 请求。这时 TCP 不会替你判断这两个请求是不是同一笔订单。业务层必须用请求 ID、订单号、幂等键等机制处理。
所以不要因为“TCP 是可靠的”就忽略接口幂等。TCP 保证的是字节流可靠交付,不保证业务操作只执行一次。支付、下单、扣库存、发券这些操作,仍然要在业务层设计幂等。
排查时怎么看重传
抓包工具里看到 TCP Retransmission,先看它是偶发还是持续。偶发重传在复杂网络里并不少见,尤其跨地域、弱网、无线网络下更常见。持续大量重传才需要重点排查链路质量、丢包、拥塞和接收端状态。
再看是超时重传还是快速重传。超时重传通常等待时间更长,说明 ACK 在 RTO 内没有回来;快速重传会伴随多个重复 ACK,说明后续数据还能到达,只是中间缺了一段。两者对应的网络状态不完全一样。
最后结合窗口和 RTT。接收窗口很小,可能是接收端处理慢;RTT 抖动大、重复 ACK 多、重传多,可能是网络拥塞或丢包;如果只有某个路径有问题,就看运营商、跨机房、代理和防火墙设备。
面试里怎么讲
如果被问 TCP 重传机制,可以先说基础:TCP 给字节编号,用确认号表示接收方下一步期望收到的字节。发送方把未确认数据保存在发送缓冲区,并为其启动重传定时器。
然后讲超时重传:如果在 RTO 内没有收到 ACK,发送方认为数据或 ACK 可能丢失,就重传对应数据段。接收方如果收到重复数据,会根据序号去重,不会把重复内容交给上层应用重复处理。
最后讲快速重传:如果接收方收到后续乱序数据,会重复确认缺失的序号;发送方收到多个重复 ACK 后,可以不等超时,立即重传缺失段。快速恢复会配合降低拥塞窗口,让连接更平滑地从丢包中恢复。
常见问题
TCP 重传会不会导致应用收到重复数据?
正常不会。TCP 接收端会根据序号识别重复数据,并按顺序把字节流交给上层。业务层看到的通常是一份有序数据,而不是重复 TCP 段。
快速重传为什么需要重复 ACK?
重复 ACK 表示接收方一直在等待同一个序号,通常说明中间某段丢了但后续数据到了。发送方据此可以提前重传缺失段,不必等 RTO 超时。
TCP 可靠了,业务接口还需要幂等吗?
需要。TCP 可靠的是字节流传输,不保证业务请求只执行一次。客户端应用层重试可能产生多次完整请求,下单、支付、扣库存等操作仍要设计幂等。