TCP头部报文如上图所示。
源端口号,目标端口号
TCP 的报文里没有 源IP和 目的IP,因为那是IP层协议的事情,TCP层只有源端口和目的端口。
源IP,源端口,目的IP,目的端口构成了 TCP 连接的 “四元组”。一个四元组可以标识一个连接。
序列号(Sequence number)
TCP 是面向字节流的协议,通过TCO传输的字节流的每个字节都会分配序列号,序列号值得是本报文段第一个字节的序列号。
序列号加上报文长度,用于确定传输的是哪一段数据。序列号是一个 32 位的无符号整数,达到 2^32-1 后循环到 0。
在 SYN 报文中,序列号用于交换彼此的初识序列号,在其他报文中,序列号用于保证包的顺序。
如果发送方发送的是四个报文段的序列号分别是: 1、2、3、4,但是到达接受方的顺序是 2、4、3、1,接受方可以通过序列号的大小顺序组装出原始的数据。
初始化序列号(Initial Sequence Number)
在建立连接之初,通信双方都会各自选择一个序列号,叫做初始化序列号。在建立连接时,通信双方通过 SYN 报文交互彼此的 ISN。
确认号(Acknowledgment number)
TCP 使用确认号来告知对方下一个期望接受的序列号,小于此确认号的所有字节都已经收到。
关于ACK有几点需要注意:
- 不是所有的包都需要确认的。
- 不是收到了数据包就立马需要确认的,可以延迟一会再确认。
- ACK 包本身不需要被确认,否则会死循环。
- 确认号永远表示小于此确认号的字节都已经收到。
TCP Flags
TCP 有很多标记,有些用来发起连接同步初识序列号,有些用来确认数据包,还有一些用来结束连接。
TCP 使用 8 bit 的字段来存储 flags。
我们通常所说的 SYN、ACK、FIN、RST 其实只是把 flags 对应的 bit 位置为 1 而已,这些标记可以组合使用,比如 SYN+ACK,FIN+ACK 等。
- SYN(Synchronize): 用于发起连接数据包同步双方的初始化序列号。
- ACK(Acknowledge):确认数据。
- RST(Reset):这个标记用来强制断开连接。
- FIN(Finish): 通知对方数据发送完毕,准备断开连接。
- PSH(Push):告知对方这些数据包收到之后马上交给应用层,不能缓存。
窗口大小
可以看出用于表示窗口大小的 Window SIze 只有 16 bit,也就是说窗口最大的大小是 65535 byte(64 KB)。为了让窗口再大一些,TCP协议引入了 “TCP 窗口缩放”选项作为窗口缩放的调控因子。调控因子的范围:0-14。