> For the complete documentation index, see [llms.txt](https://bohans.gitbook.io/ji-chu/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://bohans.gitbook.io/ji-chu/network/tcpip-wang-luo-mo-xing/wang-luo-ceng/ip-shu-ju-bao-de-ge-shi.md).

# IP 数据报的格式

<figure><img src="/files/ObiLtYugAdDMgmp41x4o" alt=""><figcaption></figcaption></figure>

一个IP数据报由**首部**和**数据**两部分组成：

* 首部的前一部分是固定长度，共 20 字节，是所有 IP 数据报必须具有的。
* 在首部的固定部分的后面是一些可选字段，其长度是可变的。

## IP 数据报首部的固定部分中的各字段

* **版本**：占 4 位，指 IP 协议的版本。
  * 通信双方使用的 IP 协议的版本必须一致。
  * 目前广泛使用的 IP 协议版本号为 4（即 IPv4）。
* **首部长度**：占 4 位，可表示的最大十进制数值是 15。

  请注意，**首部长度字段所表示数的单位是** 32 位字（1 个 32 位字长是 **4 字节**）。因为 IP 首部的固定长度是 20 字节，因此首部长度字段的最小值是 5，当 IP 分组的首部长度不是 4 字节的整数倍时，必须利用最后的填充字段加以填充。
* **区分服务**：占 8 位，用来获得更好的服务。
* **总长度**：总长度指首部和数据之和的长度，单位为字节。总长度字段为 16 位，因此数据报的最大长度为 2^16 – 1＝65535 字节。

  在进行分片时，数据报首部中的“总长度”字段是指分片后的每一个分片的首部长度与该分片的数据长度的总和。
* **标识（identification）**：占 16 位。

  **当数据报由于长度超过网络的 MTU 而必须分片时，这个标识字段的值就被复制到所有的数据报片的标识字段中**。相同的标识字段的值使分片后的各数据报片最后能正确地重装成为原来的数据报。
* **标志（flag）**：占 3 位，但目前只有两位有意义：
  * 标志字段中的最低位记为 MF（More Fragment）
    * MF＝1 表示后面“还有分片 ”的数据报
    * MF＝0 表示这已是若干数据报片中的最后一个
  * 标志字段中间的一位记为 DF（Don't Fragment），意思是“不能分片”。只有当 DF＝0 时才允许分片
* **片偏移**：占 13 位。
  * 片偏移指出：**较长的分组在分片后，某片在原分组中的相对位置**。也就是说，相对于用户数据字段的起点，该片从何处开始。
  * **片偏移以 8 个字节为偏移单位**。这就是说，每个分片的长度一定是 8 字节（64 位）的整数倍。
* **生存时间**：占 8 位，生存时间字段常用的英文缩写是 TTL（Time To Live），表明这是**数据报在网络中的寿命**。由发出数据报的源点设置这个字段。
  * **其目的是防止无法交付的数据报无限制地在互联网中兜圈子，因而白白消耗网络资源**。&#x20;
  * **TTL 的单位是跳数**。TTL 的意义是指明数据报在互联网中至多可经过多少个路由器。路由器在每次转发数据报之前就把 TTL 值减 1。若 TTL 值减小到零，就丢弃这个数据报，不再转发。
* **协议**：占 8 位，协议字段指出此数据报携带的数据是使用何种协议，以便使目的主机的 IP 层知道应将数据部分上交给哪个协议进行处理。
* **首部检验和**：占 16 位。
  * 这个字段**只检验数据报的首部**，但不包括数据部分。这是**因为数据报每经过一个路由器，路由器都要重新计算一下首部检验和**（一些字段，如生存时间、标志、片偏移等都可能发生变化），不检验数据部分可减少计算的工作量。
  * 为了进一步减小计算检验和的工作量，IP 首部的检验和不采用复杂的 CRC 检验码而采用下面的简单计算方法：
    * 在发送方，先把 IP 数据报首部划分为许多 16 位字的序列，并把检验和字段置零。用反码算术运算把所有 16 位字相加后，将得到的和的反码写入检验和字段。
    * 接收方收到数据报后，将首部的所有 16 位字再使用反码算术运算相加一次。将得到的和取反码，即得出接收方检验和的计算结果。
      * 若首部未发生任何变化，则此结果必为 0，于是就保留这个数据报。
      * 否则即认为出差错，并将此数据报丢弃。
  * **源地址**：占 32 位。
  * **目的地址**：占 32 位。

> <mark style="color:blue;">**反码求和**</mark>
>
> 两个数进行二进制反码求和的运算规则是：
>
> * 从低位到高位逐列进行计算
> * 0 和 0 相加是 0
> * 0 和 1 相加是 1
> * 1 和 1 相加是 0，但要产生一个进位 1，加到下一列
> * 若最高位相加后产生进位，则最后得到的结果要加 1

## 分片

在 IP 层下面的每一种数据链路层协议都规定了一个数据帧中的数据字段的最大长度，这称为**最大传送单元 MTU（Maximum TransferUnit）**。

当一个 IP 数据报封装成链路层的帧时，此数据报的总长度（即首部加上数据部分）一定不能超过下面的数据链路层所规定的 MTU 值。**若所传送的数据报长度超过数据链路层的 MTU 值，就必须把过长的数据报进行分片处理。**
