飞翔飞翔
主页
  • 计算机基础

    • TCP/IP协议
    • Linux命令
  • 数据库

    • SQL教程
  • 编程语言

    • C语言
    • Python2
    • Python3
  • 数据格式

    • JSON教程
  • 工具

    • Markdown指南
  • Git

    • GitFlow
  • Quartz

    • Quartz教程
  • Java

    • Java设计模式
  • 缓存

    • Redis教程
联系
阿里云
主页
  • 计算机基础

    • TCP/IP协议
    • Linux命令
  • 数据库

    • SQL教程
  • 编程语言

    • C语言
    • Python2
    • Python3
  • 数据格式

    • JSON教程
  • 工具

    • Markdown指南
  • Git

    • GitFlow
  • Quartz

    • Quartz教程
  • Java

    • Java设计模式
  • 缓存

    • Redis教程
联系
阿里云
  • 学习路径
  • IP协议

    • 认识 IP 协议与网络层定位
    • IPv4 编址体系与分类地址
    • CIDR 与子网划分实战
    • IPv6 编址体系
    • ARP 协议详解
    • NDP 协议详解
    • IGMP 与 MLD 组播侦听发现
    • VRRP 与网关冗余
    • IPv4 数据报首部解析
    • IPv6 数据报与扩展首部
    • IPsec 安全扩展
    • 分片、MTU 与路径发现
    • ICMP 与 Traceroute 原理
    • 路由基础与转发流水线
    • 动态路由协议
    • NAT 网络地址转换
    • DHCP 与自动配置
    • Wireshark 与命令行工具
    • IPv6 过渡技术
    • IP 协议栈排障与攻击防御
  • TCP协议

    • 认识 TCP 协议与传输层定位
    • TCP 报文段首部解析
    • 三次握手与连接建立
    • 四次挥手与连接释放
    • TCP 有限状态机
    • 序列号与确认机制
    • 超时重传与 RTO 计算
    • 滑动窗口与流量控制
    • 拥塞控制基础
    • 现代拥塞控制算法
    • TCP 选项与扩展
    • TCP 性能调优与内核参数
    • Nagle 算法与糊涂窗口综合征
    • TCP 定时器与 Keep-Alive 机制
    • TCP 安全与攻击防御
    • TCP 与上层/下层交互
    • TCP 综合实践与排障

TCP 报文段首部解析

TCP 报文段结构

TCP 把应用数据切成一块块**报文段(Segment)**发送。每个报文段 = TCP 首部 + 数据载荷。

+------------------+------------------+
|   TCP 首部       |   数据 Payload   |
|   20~60 字节     |   可变长度       |
+------------------+------------------+

首部固定 20 字节,选项最多 40 字节,所以首部最大 60 字节。这种"固定+可变"的设计兼顾了处理效率与扩展性。

TCP 首部 20 字节逐字段解析

把 20 字节展开成 5 行 × 32 位(每行 4 字节),这是 RFC 793 的标准画法:

 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
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|          Source Port          |       Destination Port        |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                        Sequence Number                        |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                    Acknowledgment Number                        |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|  Data |           |U|A|P|R|S|F|                               |
| Offset| Reserved  |R|C|S|S|Y|I|            Window             |
|       |           |G|K|H|T|N|N|                               |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|           Checksum            |         Urgent Pointer        |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

1. 源端口 & 目的端口(各 16 位)

标识发送方和接收方的应用进程。例如 HTTP 服务器监听 80 端口,浏览器从随机端口(如 54321)发起连接。

2. 序列号 Sequence Number(32 位)

标识本报文段发送数据的第一个字节在整个字节流中的位置。TCP 把数据视为无结构的字节流,每个字节都有隐式编号。

初始序列号(ISN)不是从 0 开始!RFC 793 建议每 4 微秒增量 1,现代系统采用更复杂的随机化策略,防止序列号预测攻击。

3. 确认号 Acknowledgment Number(32 位)

累积确认:值为"期望收到的下一个字节的序号",隐含表示该序号之前的所有数据均已正确接收。

例如收到字节 0~999,回复 Ack = 1000,表示"1000 之前的都收到了,请从 1000 开始发"。

4. 数据偏移 Data Offset(4 位)

以 4 字节为单位指示首部长度。最小值 5(5×4=20 字节,无选项),最大值 15(15×4=60 字节,选项满)。

5. 控制标志 Flags(6 位)

标志名称作用关键场景
URG紧急Urgent Pointer 有效带外数据(极少使用)
ACK确认Acknowledgment Number 有效除首个 SYN 外,所有报文都应置位
PSH推送立即交付应用层交互式应用(如 Telnet)
RST重置异常关闭连接端口未监听、连接异常
SYN同步建立连接时同步 ISN三次握手第一步
FIN结束释放连接四次挥手第一步

SYN 和 FIN 各消耗一个序列号!这是理解三次握手和四次挥手长度差异的关键。

6. 窗口大小 Window Size(16 位)

接收方通告的**接收窗口(rwnd)**大小,以字节为单位。告诉对方"我还能接收多少数据"。

原始设计最大仅 64KB(2^16-1),RFC 7323 引入窗口缩放选项后,实际窗口可达 1GB。

7. 校验和 Checksum(16 位)

覆盖 TCP 首部 + 数据 + 12 字节伪首部(包含源 IP、目的 IP、协议字段和 TCP 长度)。

伪首部的作用:检测 IP 地址错误(如路由错误导致包送到错误主机)。注意 TCP 校验和强度弱于 CRC,属于完整性保护而非安全机制。

8. 紧急指针 Urgent Pointer(16 位)

与 URG 标志配合,指示紧急数据在字节流中的结束位置。现代应用极少使用(Telnet 时代遗留)。

TCP 伪首部

+-------------------------------+
|      Source IP Address        |  32 位
+-------------------------------+
|   Destination IP Address      |  32 位
+-------------------------------+
|  Zero  |  Protocol | TCP Len  |  8+8+16 位
+-------------------------------+

校验和计算时把伪首部放在 TCP 首部前面一起计算,但伪首部不实际传输,仅在计算时使用。

TCP 选项(Options)

选项采用 TLV(Type-Length-Value) 编码,常见选项:

选项类型名称作用
2MSS最大段大小,三次握手时协商
3Window Scale窗口缩放因子,突破 64KB 限制
5SACK选择性确认,精确通告乱序段
8Timestamp时间戳,精确测 RTT + 防序列号回绕
34TFOTCP Fast Open,减少 1 个 RTT

选项仅在三次握手时通过 SYN 报文协商,连接建立后不可动态变更。

Wireshark 实战:解读一个真实 TCP 包

Transmission Control Protocol, Src Port: 54321, Dst Port: 443
    Source Port: 54321
    Destination Port: 443
    Sequence Number: 1234567890
    Acknowledgment Number: 0
    Header Length: 28 bytes (7)      ← Data Offset=7, 首部 28 字节(含 8 字节选项)
    Flags: 0x002 (SYN)               ← 只有 SYN 置位
    Window: 65535
    Checksum: 0x1234 [unverified]
    Urgent Pointer: 0
    Options: (8 bytes)
        Maximum segment size: 1460 bytes
        Window scale: 8 (multiply by 256)
        SACK permitted
        Timestamps

解读:

  • 源端口 54321(浏览器随机端口),目的端口 443(HTTPS)
  • Seq=1234567890(ISN),Ack=0(首次握手无确认)
  • Header Length=28(20 固定 + 8 选项)
  • Flags=0x002(只有 SYN)
  • 协商了 MSS=1460、Window Scale=8、SACK、Timestamp

本篇小结

  • TCP 首部固定 20 字节 + 选项最多 40 字节
  • 源/目的端口(16 位)标识应用进程
  • 序列号(32 位)标识字节流位置,ISN 随机生成
  • 确认号(32 位)采用累积确认
  • 控制标志:SYN/FIN 各消耗一个序列号;ACK 除首 SYN 外必置位
  • 窗口大小(16 位)原始最大 64KB,窗口缩放后可更大
  • 校验和覆盖首部 + 数据 + 伪首部
  • 选项 TLV 编码,握手时协商,常见:MSS/Window Scale/SACK/Timestamp/TFO

动手实践

  1. Wireshark 抓包访问一个 HTTPS 网站,找到第一个 SYN 报文,逐字段验证上述理论

  2. 计算:如果 Data Offset=8,首部多少字节?选项多少字节?

  3. 观察 SYN 报文中的选项:MSS 是多少?Window Scale 因子是多少?是否支持 SACK?

  4. 思考:为什么 SYN 和 FIN 要各消耗一个序列号?如果 SYN 不消耗序列号,三次握手会有什么问题?

上一页
认识 TCP 协议与传输层定位
下一页
三次握手与连接建立