TCP 协议的相关特性

深入理解 TCP 协议:核心特性与机制详解

TCP(Transmission Control Protocol,传输控制协议)是计算机网络中最核心、最复杂的协议之一。与 UDP 的简单粗暴不同,TCP 提供了面向连接、可靠、基于字节流的传输服务。

本文将详细剖析 TCP 的报文结构、核心特性(连接管理、可靠传输、流量控制、拥塞控制),以及开发中常见的粘包问题和状态分析。


一、TCP 报文段结构

TCP 报文段由 TCP 首部 和 TCP 数据 两部分组成。首部的前 20 个字节是固定的,后面可能有可变长度的选项。

text 复制代码
 0                   1                   2                   3
 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|          源端口号 (16)        |        目的端口号 (16)        |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                        序号 Sequence Number (32)              |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                    确认号 Acknowledgment Number (32)          |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|  数据偏移(4)  |  保留(6)  |U|A|P|R|S|F|        窗口大小 (16)    |
|              |           |R|C|S|S|Y|I|                        |
|              |           |G|K|H|T|N|N|                        |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|           校验和 (16)         |        紧急指针 (16)          |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                        选项 (长度可变)                        |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                            数据                               |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

1. 核心字段解析

  • 源端口 / 目的端口:标识发送端和接收端的应用进程。
  • 序号(Sequence Number) :TCP 是面向字节流的,序号表示本报文段所发送数据的第一个字节的序号。
  • 确认号(Acknowledgment Number):期望收到对方下一个报文段的第一个数据字节的序号。表示该序号之前的所有数据都已经正确接收。
  • 数据偏移:指出 TCP 首部的长度(因为可能有选项),单位是 32 位字(4 字节)。最小值为 5(即 20 字节)。
  • 标志位(控制位) :
    • URG:紧急指针有效。
    • ACK:确认号有效。连接建立后通常都为 1。
    • PSH:接收方应尽快将这个报文交给应用层,而不是等缓冲区满。
    • RST:重置连接(强制断开)。
    • SYN:同步序号,用于建立连接(三次握手)。
    • FIN:发送端数据发送完毕,请求释放连接(四次挥手)。
  • 窗口(Window) :接收方告诉发送方自己还能接收多少字节的数据,用于流量控制。
  • 校验和:校验首部和数据,计算时同样需要加上伪首部。

二、TCP 的核心特性

1. 面向连接(三次握手与四次挥手)

TCP 通信前必须先建立连接,通信结束后必须释放连接。

(1)三次握手(建立连接)
text 复制代码
Client                                Server
  |                                      |
  | ------------ SYN (seq=x) ---------->|  (1) 客户端请求建立连接
  |                                      |
  | <--- SYN+ACK (seq=y, ack=x+1) -------|  (2) 服务端同意并回应
  |                                      |
  | ------------ ACK (ack=y+1) --------->|  (3) 客户端确认
  |                                      |
  | <============ 连接建立 =============>|

为什么是三次?

为了确认双方的发送能力 和接收能力都正常。

  • 第一次:服务端确认了客户端的发送能力。
  • 第二次:客户端确认了服务端的接收和发送能力。
  • 第三次:服务端确认了客户端的接收能力。
    如果只有两次,服务端无法确认客户端是否收到了自己的 SYN+ACK,且可能因为网络延迟收到过期的历史连接请求,导致资源浪费。
(2)四次挥手(释放连接)
text 复制代码
Client                                Server
  |                                      |
  | ------------ FIN (seq=u) ----------->|  (1) 客户端数据发完了
  |                                      |
  | <----------- ACK (ack=u+1) ----------|  (2) 服务端确认
  |                                      |
  |         (服务端可能还有数据要发)        |
  |                                      |
  | <----------- FIN (seq=w) ------------|  (3) 服务端数据也发完了
  |                                      |
  | ------------ ACK (ack=w+1) --------->|  (4) 客户端确认
  |                                      |
  |         (等待 2MSL 后彻底关闭)         |

为什么是四次?

TCP 是全双工的,连接释放需要双方都发送 FIN。

当客户端发送 FIN 后,只表示客户端没有数据要发了,但依然可以接收数据。服务端收到 FIN 后,先回 ACK,然后处理完剩余数据,再发送自己的 FIN。因此 ACK 和 FIN 不能合并,必须分开发送。


2. 可靠传输(机制组合拳)

网络环境是不可靠的,TCP 通过以下机制保证数据不丢失、不重复、按序到达:

  • 校验和:发现数据在传输过程中的比特错误,错误则丢弃。
  • 序列号与确认应答(ACK):发送方给每个字节编号,接收方收到后回复 ACK。发送方根据 ACK 确认数据被接收。
  • 超时重传:发送方发出数据后启动定时器,如果超时未收到 ACK,则重新发送该数据。
  • 连接管理:通过三次握手和四次挥手保证连接的可靠建立和释放。
  • 丢弃重复数据:接收方通过序列号去重。

3. 流量控制(滑动窗口)

目的:防止发送方发送速度过快,导致接收方缓冲区被打满而丢包。

  • 滑动窗口机制 :接收方在 ACK 报文中的 Window 字段告诉发送方自己当前的接收窗口大小(即还能接收多少数据)。
  • 零窗口 :如果接收方缓冲区满了,会发送窗口大小为 0 的报文。此时发送方停止发送,并启动持续计时器,定时发送零窗口探测报文,询问接收方窗口是否变大。

4. 拥塞控制

目的:防止过多的数据注入到网络中,导致路由器或链路过载(全局性问题)。

TCP 采用四种算法协同工作:

  1. 慢启动(Slow Start) :
    • 刚建立连接时,拥塞窗口(cwnd)设为 1 个 MSS(最大报文段长度)。
    • 每收到一个 ACK,cwnd 翻倍(指数增长)。
    • 达到慢启动阈值(ssthresh)后,进入拥塞避免。
  2. 拥塞避免(Congestion Avoidance) :
    • 每个 RTT(往返时间),cwnd 加 1(线性增长),让网络慢慢试探上限。
  3. 快重传(Fast Retransmit) :
    • 如果发送方连续收到 3 个重复的 ACK(说明某个包丢了,但后续包收到了),立即重传丢失的报文,而不必等超时定时器到期。
  4. 快恢复(Fast Recovery) :
    • 执行快重传后,将 ssthresh 和 cwnd 减半,然后直接进入拥塞避免状态,而不是回到慢启动。

5. 面向字节流与全双工

  • 全双工:TCP 允许通信双方在同一时刻互相发送数据。两端都有发送缓冲区和接收缓冲区。
  • 面向字节流:TCP 把应用层交下来的数据看成是一连串的无结构字节流。它不保留应用层消息的边界。

三、TCP 的常见问题与注意点

1. 粘包与拆包

由于 TCP 是面向字节流 的,它没有消息边界。如果发送方连续发送两条消息 "Hello" 和 "World",接收方可能会一次读取到 "HelloWorld",这就是粘包 ;也可能一次只读到了 "Hel",这就是拆包。

产生原因:

  • 发送方使用了 Nagle 算法(合并小包发送)。
  • 接收方应用层读取不及时,缓冲区积累了多个包。
  • 数据包大于 MSS,发生 IP 分片。

解决方案(应用层协议设计):

  1. 定长消息:规定每个消息固定长度,不够补齐(浪费带宽)。
  2. 特殊分隔符 :如使用 \r\n 作为消息结束标志(如 HTTP 协议)。
  3. 长度前缀:在消息头部用固定几个字节标明消息体长度(最常用,如 Protobuf、Dubbo)。

2. 常见 TCP 状态解析

  • LISTEN:服务端套接字处于监听状态,等待客户端连接。
  • ESTABLISHED:连接已建立,正常通信状态。
  • CLOSE_WAIT:被动关闭方收到对方的 FIN,但自己还没调用 close()。如果大量出现,说明代码有 Bug(忘记关闭连接)。
  • TIME_WAIT:主动关闭方最后进入的状态,等待 2MSL(报文最大生存时间的两倍)后彻底关闭。
    • 作用 1:确保最后一个 ACK 能被对方收到。如果 ACK 丢失,对方会重发 FIN,此时处于 TIME_WAIT 的一方可以再次回复 ACK。
    • 作用 2:防止历史连接的数据包干扰新建立的连接。

3. 长连接与短连接

  • 短连接:每次请求都经历"建立连接 -> 传输数据 -> 断开连接"。简单,但三次握手和四次挥手开销大。
  • 长连接:建立连接后,保持连接不断开,多次请求复用同一个 TCP 连接。性能高,但需要心跳机制(KeepAlive)维持连接,防止长时间无数据被防火墙掐断。

四、总结

TCP 协议通过一系列精妙的机制,在不可靠的 IP 网络层之上构建了可靠的传输通道:

  • 三次握手、四次挥手实现了安全的连接管理。
  • 序列号、确认应答、超时重传保证了可靠性。
  • 滑动窗口实现了流量控制,避免压垮接收方。
  • 慢启动、拥塞避免实现了拥塞控制,避免压垮网络。
  • 面向字节流的特性要求我们在应用层处理好粘包/拆包问题。

深刻理解 TCP 的这些特性,不仅有助于应对面试,更是编写高性能、高可靠网络程序(如 RPC 框架、网关、消息队列)的基石。

相关推荐
FPGA信号处理1 小时前
【人工神经网络】第一讲:竞争网络与自组织特征映射:从胜者为王到保序映射
网络
2501_916007472 小时前
抓包工具功能对比,TraceEagle、Charles、Fiddler、Wireshark、mitmproxy 差别
前端·网络协议·ios·adb·https·fiddler·wireshark
吴声子夜歌2 小时前
Kubernetes权威指南——Kubernetes安装配置指南(网络配置)
网络·容器·kubernetes
硅基造物主2 小时前
STM32 从 0 到 1 做智能家居(十二):USART2 分时复用 —— ESP-12F + MQTT
网络·stm32·mqtt·智能家居·esp-12f
我不会起名字3222 小时前
TCP 三次握手为什么是三次:丢包、重传与初始序列号
网络·tcp·原理·握手
Yang96112 小时前
鼎讯信通DXA-3S光纤熔接机:光缆教学中的技术精粹解析
网络
xbzb3 小时前
IP、掩码、网关、DNS 到底谁管什么?网络基础与七种设备一次讲清
网络·网关·mac·ip·dns·掩码
前进吧-程序员4 小时前
C++20 协程入门实战:从 co_await 到一个 100 行的异步任务调度器
网络·c++·c++20
前进吧-程序员4 小时前
实战:C++20 协程 + io_uring 写一个 400 行的 echo server
网络·c++·c++20
云飞云共享云桌面5 小时前
机械制造研发部门:一台SolidWorks云主机替代 10 台传统图形工作站
运维·服务器·网络·3d·自动化·制造