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
:窗口缩放选项