TCP 是怎么保证可靠传输的?

一则或许对你有用的小广告

欢迎 加入小哈的星球 ,你将获得: 专属的项目实战(已更新的所有项目都能学习) / 1v1 提问 / Java 学习路线 / 学习打卡 / 每月赠书 / 社群讨论

  • 新开坑项目: 《Spring AI 项目实战(问答机器人、RAG 增强检索、联网搜索)》 正在持续爆肝中,基于 Spring AI + Spring Boot3.x + JDK 21...点击查看;
  • 《从零手撸:仿小红书(微服务架构)》 已完结,基于 Spring Cloud Alibaba + Spring Boot3.x + JDK 17...点击查看项目介绍; 演示链接: http://116.62.199.48:7070/;
  • 《从零手撸:前后端分离博客项目(全栈开发)》 2 期已完结,演示链接: http://116.62.199.48/

面试考察点

  1. 基础掌握度:面试官不仅仅是想知道你能否背诵 TCP 的特性,更是想知道你是否理解可靠传输的底层机制——从校验和到流量控制,从确认应答到重传机制,每一层是如何协同工作的。

  2. 系统性思维:考察你是否能从发送端、接收端、网络环境三个维度来系统分析可靠性保障,而不是零散地列举知识点。

  3. 实践应用意识:如果你了解这些机制,在实际开发中遇到网络问题时(如超时、丢包),能否快速定位是哪一层的可靠性机制出了问题。

核心答案

TCP 通过 7 大核心机制 协同保障可靠传输:

机制作用解决的问题
校验和检测数据在传输过程中是否变化数据损坏
序列号给每个字节编号,确保有序乱序、重复
确认应答 (ACK)告知发送方已收到哪些数据丢包检测
重传机制超时或收到重复 ACK 时重发数据丢失
流量控制滑动窗口控制发送速率接收方处理不过来
拥塞控制动态调整发送窗口网络拥堵
连接管理三次握手、四次挥手建立和终止可靠连接

一句话总结:TCP 通过 "编号-确认-重传" 三部曲,配合流量控制和拥塞控制,在不可靠的 IP 层之上构建了可靠的数据传输通道。

深度解析

一、序列号与确认应答 (ACK) —— 可靠传输的基石

TCP 给每个字节的数据都分配了一个序列号(Sequence Number,简称 SEQ),接收方通过确认应答(Acknowledgment Number,简称 ACK)告诉发送方:"我期望收到的下一个序列号是多少"。

上图展示了 TCP "发送-确认" 的基本流程。关键点如下:

  1. 序列号 (SEQ):发送方发送数据时,TCP 头部携带序列号,表示这段数据的第一个字节的编号。例如 SEQ=1 表示这 100 字节的编号是 1~100。

  2. 确认号 (ACK):接收方回复的 ACK 号表示"我期望收到的下一个字节的序列号"。收到 SEQ=1 的 100 字节后,回复 ACK=101,表示 "1~100 我都收到了,请从 101 开始发"。

  3. 累积确认:TCP 采用累积确认机制,ACK=201 表示 200 及之前的所有数据都已正确接收。即使中间有乱序到达的包,也必须等到中间缺失的包补齐后才能确认。

二、重传机制 —— 应对丢包的利器

网络中丢包是常态,TCP 通过两种重传机制来保证数据最终送达:

1. 超时重传 (RTO)

发送方发出数据后启动一个定时器(RTO,Retransmission Timeout),如果在定时器到期前没有收到 ACK,就重传数据。

上图展示了超时重传的过程:

  1. RTO 计算:RTO 不是固定值,而是根据网络往返时间(RTT)动态计算的。经典公式:RTO = RTT均值 + 4 × RTT偏差,这样既能快速响应,又能避免误判。

  2. 指数退避:如果第一次重传仍然超时,RTO 会指数级增长(×2),避免在网络拥塞时雪上加霜。

  3. 超时阈值:Linux 默认重传次数为 15 次,超过后放弃连接。

2. 快速重传 (Fast Retransmit)

超时重传需要等待较长时间,快速重传通过 "收到 3 个重复 ACK" 来更快地检测丢包:

上图展示了快速重传的核心逻辑:

  1. 重复 ACK 触发:接收方收到 SEQ=201、301、401 后,因为缺少 101,会连续回复 ACK=101。发送方收到 3 个重复 ACK 后,立即重传 SEQ=101,无需等待超时。

  2. 速度优势:超时重传需要等待 RTO(通常几十到几百毫秒),而快速重传在收到第 3 个重复 ACK 时立即触发,响应速度快得多。

  3. 与拥塞控制配合:快速重传后会触发快速恢复算法,窗口减半而不是降到 1,避免过度降速。

三、滑动窗口 —— 效率与可靠性的平衡

如果每发一个包都要等 ACK,效率太低。滑动窗口允许发送方连续发送多个包而不必等待确认,同时保证可靠性:

上图展示了滑动窗口的核心原理:

  1. 窗口划分:发送方的数据分为四部分——已发送且确认、已发送未确认、可发送(在窗口内但未发)、不可发送(窗口外)。

  2. 滑动机制:每收到一个 ACK,窗口向右滑动相应字节数,允许发送新数据。收到 ACK=201 后,窗口右移 100 字节,现在可以发送 401~600。

  3. 效率提升:窗口大小决定了发送方的"飞行中"数据量。窗口越大,吞吐量越高(在带宽允许的前提下)。

  4. 可靠性保证:窗口内的未确认数据必须保留副本,以便重传。只有收到 ACK 后,数据才能真正从发送缓冲区删除。

四、流量控制 —— 保护接收方

发送方发得太快,接收方处理不过来怎么办?TCP 通过 接收窗口 (rwnd) 实现流量控制:

上图展示了流量控制的工作原理:

  1. 接收窗口 (rwnd):接收方在 TCP 头部的 Window 字段中通告自己的剩余缓冲区大小。发送方的发送窗口不能超过这个值。

  2. 动态调整:应用层从缓冲区读取数据后,剩余空间增大,rwnd 变大,通过 ACK 告知发送方可以加速。

  3. 零窗口探测:当 rwnd=0 时,发送方停止发送。但为了知道窗口何时恢复,发送方会定期发送 1 字节的探测包,触发接收方回复最新的窗口大小。

五、拥塞控制 —— 保护网络

流量控制保护的是接收方,拥塞控制保护的是整个网络。TCP 通过 4 个核心算法 实现拥塞控制:

上图展示了拥塞窗口的动态变化过程:

  1. 慢启动阶段:连接刚建立时,cwnd 从 1 MSS 开始,每收到一个 ACK 就翻倍。虽然叫"慢"启动,但实际上是指数增长,很快就能达到较高速度。

  2. 拥塞避免阶段:当 cwnd 超过 ssthresh 后,改为每个 RTT 增加 1 MSS 的线性增长。这是为了更谨慎地探测网络容量,避免突然打爆网络。

  3. 快速重传/恢复:收到 3 个重复 ACK 时,认为发生了轻度拥塞(个别包丢失),cwnd 减半后继续传输,不必从头开始。

  4. 超时处理:发生超时时,认为网络严重拥塞,cwnd 降为 1,重新开始慢启动。这是最激进的降速措施。

六、校验和 —— 检测数据损坏

TCP 头部有一个 16 位的校验和字段,用于检测数据在传输过程中是否被损坏:

七、连接管理 —— 三次握手与四次挥手

可靠传输的前提是建立可靠的连接,TCP 通过三次握手建立连接,四次挥手断开连接:

三次握手的核心目的:

  1. 确认双方收发能力:第一次握手确认客户端能发,第二次确认服务端能收能发,第三次确认客户端能收。

  2. 同步初始序列号 (ISN):双方交换各自的初始序列号,作为后续数据传输的起点。ISN 不是从 0 或 1 开始,而是基于时钟的随机值,防止序列号猜测攻击。

  3. 防止历史连接:如果网络中滞留的旧 SYN 包到达服务端,第三次握手可以让服务端识别并拒绝。

四次挥手的核心原因:

  1. TCP 是全双工:每个方向都需要单独关闭。被动方收到 FIN 后,只是表示主动方不再发送数据,但被动方可能还有数据要发。

  2. 为什么不是三次:第二次和第三次挥手不能合并,因为被动方可能还有数据要发送,需要等待应用层调用 close()。

  3. 2MSL 等待:主动关闭方在发送最后一个 ACK 后,等待 2MSL(Maximum Segment Lifetime)时间,确保被动方收到 ACK,并让网络中的旧包消亡。

面试高频追问

  1. 追问一:TCP 和 UDP 的区别是什么?为什么 UDP 不可靠,什么场景适合用 UDP?

    • TCP 面向连接、可靠、有序、有流量/拥塞控制;UDP 无连接、不可靠、无序、无控制。UDP 适合实时性要求高、可容忍丢包的场景(视频直播、DNS、游戏)。
  2. 追问二:什么是 TCP 粘包/拆包?如何解决?

    • TCP 是字节流协议,没有"消息边界",多个小包可能被合并发送(粘包),大包可能被拆分(拆包)。解决方案:固定长度、分隔符、长度字段 + 数据。
  3. 追问三:为什么三次握手不是两次或四次?

    • 两次无法确认客户端的接收能力,也无法防止历史连接;四次可以但没必要,第二次和第三次握手可以合并。
  4. 追问四:TIME_WAIT 状态有什么作用?为什么需要等待 2MSL?

    • 确保 ACK 到达被动方(如果丢失,被动方会重发 FIN);让网络中的旧包消亡,避免影响新连接。

常见面试变体

  • 变体一:"TCP 的流量控制和拥塞控制有什么区别?"
  • 变体二:"TCP 重传机制有几种?超时重传和快速重传有什么区别?"
  • 变体三:"TCP 滑动窗口的作用是什么?和拥塞窗口有什么关系?"
  • 变体四:"为什么 TCP 需要三次握手?两次握手行不行?"

记忆口诀

可靠传输七机制:校验和(检测损坏)+ 序列号(编号防乱)+ 确认应答(告知收到)+ 重传机制(丢失重发)+ 滑动窗口(效率提升)+ 流量控制(保护接收方)+ 拥塞控制(保护网络)。

重传两种方式:超时重传(等 RTO)+ 快速重传(3 个重复 ACK)。

拥塞控制四算法:慢启动(指数)→ 拥塞避免(线性)→ 快速重传/恢复(轻度拥塞)→ 超时重置(严重拥塞)。

总结

TCP 通过 "编号-确认-重传" 三部曲确保每个字节都能准确送达,通过 滑动窗口 提升传输效率,通过 流量控制 保护接收方不被打爆,通过 拥塞控制 保护网络不拥堵。这 7 大机制协同工作,在不可靠的 IP 层之上构建了可靠的数据传输通道。