# TCP 报文结构

```
 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        |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                    Options                    |    Padding    |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                              data                             |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

                          TCP Header Format
```

* Source Port 源端口，占用 16bit=2byte；
* Destination Port 目标端口，占用 16bit=2byte；
* Sequence Number 序号，占用 32bit=4byte。序号值的范围是 \[0, 2^32 - 1]，共 2^32 个序号。序号值增加到 2^32 - 1 之后就又回到 0。TCP 是面向字节流的协议，在 TCP 连接中所传输的字节流的每一个字节都是按顺序编码的，字节流的起始序号必须在建立连接时（通过三次握手）被设置。序号值表示 **本报文段所发送的数据的第一个字节序号**。例如，一个报文段的序号值是 301，而携带的数据共有 100byte，这表明该报文段携带的数据的第一个字节的序号是 301，最后一个字节的序号是 400，并且下一个报文段的数据序号应当是从 401 开始的；
* Acknowledgment Number 确认号，占用 32bit=4byte。确认号值表示 **期望收到对方的下一个报文段的序号值**。例如， B 正确收到了 A 发送过来的报文段，其序号值是 501，携带的数据共有 200byte，如果 B 正确收到了 A 发送的序号值到 700 为止的数据，那么 B 期望收到 A 的下一个报文段的序号值是 701，因此 B 发送给 A 的确认报文段中的确认号应该为 701；
* Data Offset 数据偏移，占用 4bit。数据偏移字段表示 TCP 报文段中的数据距离 TCP 报文段起始处的偏移量；
* Reserved 保留，占用 6bit。保留字段用于未来使用，目前该字段值设置为 0；
* 六个控制位
  * URG 用于表示紧急指针字段是有效的。
  * ACK 用于表示确认号字段是有效的。**TCP 协议规定在建立连接之后的所有报文段中，都必须把 ACK 字段设置为 1**；
  * PSH 用于表示使用 push 操作；
  * RST 用于重新建立连接；
  * SYN 用于在建立连接时同步序号。当 SYN=1 ACK=0 时表示当前报文段是一个请求连接报文段，当 SYN=1 ACK=1 时表示当前报文段是一个同意请求连接的报文段；
  * FIN 用于释放连接。当 FIN=1 时表示当前报文段的发送方已经发送数据完毕；
* Window 窗口，占用 16bit=2byte。窗口值的范围是 \[0, 2^16 - 1]。窗口指的是 **当前报文段的发送方的接收窗口**（而不是发送窗口）。窗口值 **告诉对方**：从本报文段首部中的确认号算起，接收方目前允许对方发送的数据量（以字节为单位）。接收方的数据缓存空间是有限的，接收方的窗口值是作为发送方设置其发送窗口的依据。例如，一个报文段的确认序号是 701，窗口字段是 1000，这对与接收方来说，表明从 701 号算起，发送方的接收缓存空间还可以接收 1000 个字节数据，并且接收方在发送数据的时候需要考虑这一点；
* Checksum 校验和，占用 16bit=2byte。校验和字段用于校验 TCP 首部和数据两部分；
* Urgent Pointer 紧急指针，占用 16bit=2byte；
* Options 选项，可变长度，最大可占用 40byte；
* Padding 填充，作为 Options 的填充内容。

## 参考资料

* [RFC 793 - Transmission Control Protocol - Header Format](https://tools.ietf.org/html/rfc793#section-3.1)
