TCP 包头不包含 options 字段为 128bit(16byte) 的固定长度,其结构如下图所示:

---
title: "TCP Packet"
---
packet-beta

0-15: "Source Port"
16-31: "Destination Port"
32-63: "Sequence Number"
64-95: "Acknowledgment Number"
96-99: "Data Offset"
100-103: "Reserved"
104: "CWR"
105: "ECE"
106: "URG"
107: "ACK"
108: "PSH"
109: "RST"
110: "SYN"
111: "FIN"
112-127: "Window"
128-143: "Checksum"
144-159: "Urgent Pointer"
160-191: "(Options and Padding)"
192-255: "Data (variable length)"

端口号 Port

包头前 4 bytes 分别为源端口号和目标端口号。TCP 中是没有源 IP 和目标 IP 地址的,因为那是 IP 协议的事情,整个 TCP 报文是被包在 IP 报文中的。

序列号 Sequence Number

序列号指的是当前报文数据中第一个字节的序列号。序列号加上当前报文长度就可以确认当前报文传输的是哪一段数据。本身为一个 uint32,溢出后会循环到 0。

在握手阶段双方发送 SYN 报文时,会选择自己的初始序列号。

确认号 ACK

TCP 利用确认号告诉对方,自己期望的接受下一个序列号是多少,确认这个序列号之前的数据已经全部接受。

注意

  • 不是所有的包都需要确认的
  • 不是收到了数据包就立马需要确认的,可以延迟一会再确认
  • ACK 包本身不需要被确认,否则就会无穷无尽死循环了
  • 确认号永远是表示小于此确认号的字节都已经收到

标志位 Flags

标志位用来标识当前 TCP 包用做什么作用,将对应的 bit 置为 1 即表示标志开启,常用的有:

  • SYN:用于发起连接同步初始序列号
  • ACK:确认数据包
  • RST:强制断开连接
  • FIN:通知对方我发完了所有数据,准备断开连接,后面我不会再发数据包给你了
  • PSH:告知对方这些数据包收到以后应该马上交给上层应用,不能缓存起来

窗口大小 Window

窗口大小用来表示自己的还能接受数据量,发送方发送的数据长度不能超过这个数值。

最初 TCP 设计时只预留了 2bytes 的空间给窗口大小,最大只能支持 64KB,为了解决这个问题,TCP 可以在握手时在选项中通过窗口缩放选项(Window Scale Option)协商缩放因子,范围为 [0, 14]。开启之后实际的窗口大小为 Window * (2^factor)

可选项 Options

正如在窗口大小中看到的一样,Options 用来对 TCP 链接进行协商设置,用于开启或关闭某些功能与特性。

常用的有:

  • MSS:最大段大小选项,是 TCP 允许的从对方接收的最大报文段
  • SACK:选择确认选项
  • Window Scale:窗口缩放选项