TCP协议

基本定义

传输控制协议(Transmission Control Protocol)

  • OSI模型第四层(传输层)

  • 面向连接的可靠字节流服务

    • 面向连接(连接建立与释放,只能一对一,不能像UDP一对多)
    • 可靠传输(确认应答 + 超时重传 + 校验 + 有序传输 + 流量控制 + 拥塞控制)
    • 面向字节流(数据以字节流方式发送,不保留消息边界。且有序的,当「前一个」TCP 报文没有收到的时候,即使它先收到了后面的 TCP 报文,那么也不能扔给应用层去处理,同时对「重复」的 TCP 报文会自动丢弃)
  • 全双工通信模式(双方可以同时发送和接收)

  • RFC 793标准定义

什么是连接

报文格式

 1+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 2|       Source Port(16bit)       |     Destination Port(16bit)    |
 3+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 4|                       Sequence Number(32bit)                    |
 5+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 6|                 Acknowledgment Number(32bit)                    |
 7+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 8|  Data  |       |C|E|U|A|P|R|S|F|                                |
 9| Offset | Rsvd  |W|C|R|C|S|S|Y|I|             Window             |
10| (4bit) |(4bit) |R|E|G|K|H|T|N|N|             (16bit)            |
11+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
12|       Checksum(16bit)          |     Urgent Pointer(16bit)      |
13+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
14|                    Options                      |    Padding    |
15+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

TCP 首部最小 20 字节,最大 60 字节(含可选项)

字段 长度 描述
源端口(Source Port) 16 位 源端口号
目的端口(Destination Port) 16 位 目标端口号
序列号(Sequence Number) 32 位 数据字节流的起始序号,用来解决网络包乱序问题
确认号(Acknowledgment Number) 32 位 期望接收的下一个字节的序号,用来解决丢包的问题
数据偏移(Data Offset) 4 位 首部长度(以 4 字节为单位,最大15 * 4 = 60 B)
保留 4 位 保留位,未使用
控制位(Flags) 8 位 各类控制标志
窗口大小(Window Size) 16 位 表示接收方缓冲区剩余容量
校验和(Checksum) 16 位 整个 TCP 报文段的 CRC 校验值
紧急指针(Urgent Pointer) 16 位 紧急数据的偏移量(配合 URG 位使用)
可选项(Options) 可变 例如时间戳、窗口扩大等
控制位 作用
CWR Congestion Window Reduced
ECE ECN-Echo
URG 紧急指针有效
ACK 确认号有效,除了最初建立连接时的 SYN 包之外该位必须设置为 1
PSH 提示尽快推送数据给应用层
RST 复位连接,TCP 连接中出现异常必须强制断开连接(复位报文段)
SYN 同步序列号,用于建立连接(同步报文段)
FIN 终止连接(结束报文段)

连接管理

状态机

(包含11个状态转换节点) LISTEN 监听连接请求

  • SYN-SENT:发送了 SYN,等待对方确认 SYN_RCVD
  • SYN-RECEIVED:收到对方 SYN,已发送 SYN+ACK ESTABLISHED
  • ESTABLISHED:连接已建立 FIN_WAIT_1 FIN_WAIT_2 TIME_WAIT
  • FIN-WAIT-1/2、CLOSE-WAIT:连接关闭过程中的中间状态
  • TIME-WAIT:主动关闭方等待 2MSL CLOSED
  • CLOSED:连接关闭完成

连接建立

三次握手(Three-way Handshake)

  1. Client → Server: [SYN] Seq=x
  2. Server → Client: [SYN+ACK] Seq=y Ack=x+1
  3. Client → Server: [ACK] Seq=x+1 Ack=y+1

完成后,双方进入 ESTABLISHED 状态,可以开始传输数据。

第一次握手丢失

第二次握手丢失

第三次握手丢失

连接释放

四次挥手(Four-way Handshake)

  1. HostA → HostB: [FIN] Seq=u
  2. HostB → HostA: [ACK] Ack=u+1
  3. HostB → HostA: [FIN+ACK] Seq=v
  4. HostA → HostB: [ACK] Ack=v+1

客户端进入 TIME_WAIT 状态等待 2MSL(最大报文生存时间)后关闭。

第一次挥手丢失

第二次挥手丢失

第三次挥手丢失

第四次挥手丢失

可靠传输机制

序列号与确认号

每个 TCP 报文段都有序列号,确认号用于应答已收到的数据字节。 序列号分配:每个字节唯一编号

累积确认

ACK=N表示N之前所有数据已接收

超时重传

超时重传(Retransmission Timeout, RTO) 动态计算RTT,指数退避重传

数据校验和

对 TCP 首部、数据和伪首部(包括 IP 地址等)计算校验和,防止数据损坏。

流量控制

流量控制(Flow Control)利用窗口机制(Window Size)来控制发送方速率,防止接收方缓冲区溢出。

  • 接收窗口动态变化,根据接收能力调整。
  • 发送窗口由 [已确认序号, 未确认序号, 可用窗口大小] 决定。 滑动窗口动态调整: 发送窗口 = min(拥塞窗口, 接收方通告窗口) 窗口缩放选项支持扩大至1GB

拥塞控制

用于控制网络中的数据流量,防止过载。

常用算法:

  1. 慢开始(Slow Start)
    • 初始拥塞窗口 cwnd=1,指数增长(每收到 ACK cwnd += 1)
  2. 拥塞避免(Congestion Avoidance)
    • cwnd 达到阈值后线性增长
  3. 快重传(Fast Retransmit)
    • 连续收到 3 个重复 ACK,立即重传缺失报文
  4. 快恢复(Fast Recovery)
    • 阈值减半,cwnd 设置为阈值,避免重回慢启动阶段

拥塞窗口(cwnd)

  • 发送方根据 cwnd 和接收窗口大小控制实际发送量:Effective Window = min(cwnd, rwnd)

慢启动 → 拥塞避免 → 快速重传/快速恢复 经典算法:Tahoe/Reno/NewReno/CUBIC

关键算法

Nagle算法:减少小包发送 Karn算法:处理重传RTT测量 SACK选项:选择性确认机制

典型应用

  • Web(HTTP/HTTPS)
  • 邮件(SMTP/POP3/IMAP)
  • 文件传输(FTP)
  • SSH、Telnet 等远程登录

HTTP/HTTPS | SSH | SMTP | 数据库连接 需可靠传输的场景优先选择TCP

抓包分析要点

SYN/FIN标志位 | 序列号连续性 | 窗口大小变化 重传计数 | 选项字段解析 | RTT计算

调优参数

net.ipv4.tcp_keepalive_time = 7200 net.ipv4.tcp_max_syn_backlog = 1024 net.ipv4.tcp_slow_start_after_idle = 0

常见攻击与防御

  • SYN Flood 攻击:伪造大量 SYN 请求,占用连接资源
    • 防御方法:SYN Cookie、加速超时、限制半连接数
  • RST 注入攻击:伪造 RST 报文断开连接
  • TCP 会话劫持:猜测序列号篡改连接

与 UDP 对比

特性 TCP UDP
是否连接
可靠性 可靠(重传 + 确认) 不可靠
顺序性 有序传输 可能乱序
开销 较大
适用场景 文件传输、HTTP 视频、DNS、VoIP

参考协议文档:RFC 793(TCP),RFC 1122,RFC 5681(拥塞控制)

UDP和TCP可以使用同一个端口吗?

存在问题

队头阻塞

队头阻塞(Head-of-Line Blocking,HOL Blocking)是计算机网络中的一个经典问题,指在顺序处理的数据流中,一个数据包的延迟或丢失会导致后续数据无法被及时处理。这种现象类似于堵车时,一辆车抛锚会阻塞后面所有车辆。根据发生位置不同,队头阻塞可分为传输层队头阻塞和应用层队头阻塞。

  1. 传输层队头阻塞(TCP 的典型问题) 问题根源 TCP 的可靠性机制: TCP 是面向字节流的协议,所有数据必须按顺序交付。假设发送方发送了数据包 A、B、C,若包 B 丢失,即使包 A 和 C 已到达接收方,接收方也无法将包 C 传递给应用层,必须等待包 B 重传成功。

单一路径的串行处理: TCP 将所有数据视为单一连续流,即使通过多线程或分片(如 HTTP/1.1 的管道化)发送,丢失一个包仍会阻塞整个连接。

示例场景 网页加载: 一个网页需要加载 10 个资源(图片、CSS、JS),若某个资源对应的 TCP 包丢失,即使其他资源已到达浏览器,也会被阻塞,直到丢失包重传完成。

视频流传输: 视频的 I 帧(关键帧)丢失会导致后续 P 帧无法解码,即使后续帧已到达客户端,画面仍会卡顿。

QUIC 的解决方案 多路复用流(Multiplexed Streams): QUIC 允许在单个连接中创建多个独立的流(Stream),每个流独立处理数据包。若流 1 的包丢失,流 2、3 的数据仍可继续处理。

流的隔离性:每个流有自己的序号和可靠性机制,互不影响。

示例:网页中的 CSS 和图片分属不同流,CSS 流丢包不会阻塞图片流的传输。

  1. 应用层队头阻塞(HTTP/1.1 的典型问题) HTTP/1.1 的管道化(Pipelining)缺陷 请求-响应必须按序处理: 客户端通过一个 TCP 连接发送多个 HTTP 请求(如请求 HTML、CSS、JS),但服务器必须按顺序返回响应。若第一个响应延迟,后续所有响应都会被阻塞。

浏览器实际禁用管道化: 由于队头阻塞问题,主流浏览器默认禁用 HTTP/1.1 管道化,转而使用多个 TCP 连接并行请求,但这增加了连接开销。

HTTP/2 的改进与局限 多路复用(Multiplexing): HTTP/2 允许在单个 TCP 连接上并行传输多个请求和响应(通过分帧和流 ID),解决了应用层的队头阻塞。例如,一个大的 JS 文件响应不会阻塞小的 CSS 文件响应。

仍受限于 TCP 的传输层队头阻塞: 若底层 TCP 包丢失,HTTP/2 的所有流仍会被阻塞,因为 TCP 需要保证数据按序到达。

  1. QUIC 如何彻底解决队头阻塞? QUIC 在传输层和应用层同时规避了队头阻塞:

传输层:

每个流独立处理数据包,丢失的包仅影响对应流。

示例:流 1 的包 2 丢失时,流 2 的包 3、4 仍可被处理。

应用层(HTTP/3):

HTTP/3 基于 QUIC 的多路复用流,每个资源对应一个流,彻底消除应用层依赖传输层顺序的问题。

即使某个流因丢包被阻塞,其他流仍可正常传输。

  1. 队头阻塞的直观对比 场景 TCP + HTTP/1.1 TCP + HTTP/2 QUIC + HTTP/3 传输层队头阻塞 严重(单流串行处理) 严重(依赖 TCP 单流) 无(多流独立处理) 应用层队头阻塞 严重(按序响应) 无(多路复用) 无(多路复用 + 多流)
  2. 现实中的队头阻塞案例 高延迟网络: 在卫星通信或移动网络中,TCP 丢包重传会导致整个连接卡顿,QUIC 仅影响部分流。

多资源网页: 使用 HTTP/2 的网站在 TCP 丢包时,页面加载时间可能增加 50% 以上;而 HTTP/3 可保持其他资源加载不受影响。

总结 队头阻塞本质是顺序依赖导致的性能瓶颈,分为传输层和应用层两种。

QUIC 通过多路复用和流隔离,在传输层消除了队头阻塞,而 HTTP/3 在此基础上进一步优化了应用层性能。

该设计使 QUIC 在高丢包、高延迟网络中表现显著优于 TCP,成为现代 Web 和实时通信的核心协议。