# 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)


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://gitbook.fantasticmao.cn/tech/wang-luo-xie-yi/tcp-xie-yi/tcp-bao-wen-jie-gou.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
