网络协议(八):IP 协议

目录

[1. IP 协议简介](#1. IP 协议简介)

[2. 首部属性](#2. 首部属性)

[2.1 版本号](#2.1 版本号)

[2.2 首部长度](#2.2 首部长度)

[2.3 服务类型](#2.3 服务类型)

[2.4 总长度](#2.4 总长度)

[2.5 => 16位标识 & 3位标志 & 13位片偏移](#2.5 => 16位标识 & 3位标志 & 13位片偏移)

[2.5.1 => 16 位标识](#2.5.1 => 16 位标识)

[2.5.2 => 3 位标志](#2.5.2 => 3 位标志)

[2.5.3 => 13 位片偏移](#2.5.3 => 13 位片偏移)

[2.6 生存时间(TTL)](#2.6 生存时间(TTL))

[2.7 => 8 位协议](#2.7 => 8 位协议)

[2.8 首部校验和](#2.8 首部校验和)

[2.9 源/目的 IP 地址](#2.9 源/目的 IP 地址)

[3. 地址管理](#3. 地址管理)

[3.1 动态分配](#3.1 动态分配)

[3.2 NAT 机制 [主力方案]](#3.2 NAT 机制 [主力方案])

[3.2.1 NAT 网络地址映射](#3.2.1 NAT 网络地址映射)

[3.3 IPv6](#3.3 IPv6)

[3.4 网段划分](#3.4 网段划分)

[3.4.1 网络号和主机号](#3.4.1 网络号和主机号)

[3.4.2 子网掩码](#3.4.2 子网掩码)

[3.5 特殊的 IP 地址](#3.5 特殊的 IP 地址)

[4. 路由选择](#4. 路由选择)


1. IP 协议简介

IP 协议, 是网络层的协议, 和 TCP 一样, 也是 TCP/IP 协议栈的 "冠名协议" 之一. 同样, 其复杂程度和 TCP 差不多(都非常复杂).

但是作为 Java 程序员, 我们只需关注应用层和传输层即可, 对于网络层的 IP 协议, 我们了解即可. 所以本篇博客, 不会展开介绍 IP 协议的详细内容.

IP 协议 / 网络层, 主要的工作有以下两个:

  1. 地址管理: 通过 IP 地址, 来标识网络上的某个设备的位置.
  2. 路由选择: 在两个通信的节点之间, 规划出一条合理的路径.

2. 首部属性

IP 协议的报文格式如下:

2.1 版本号

虽然版本号有 6 位, 但是目前使用的 IP 协议版本只有两种:

  1. IPv4 [本篇讨论]
  2. IPv6 (近几年才多起来)

本篇讨论的均为 IPv4 协议.

2.2 首部长度

由于 选项 这一属性, 使得 IP 协议的首部长度也是可变的.

首都长度 一共有 4 位, 可表示的范围是 0 ~ 0xF, 依旧以 4 字节为单位, 故最大首部长度为 0xF(15) * 4 => 60 字节.

其中, 固定部分为 20 字节, 选项部分最多为 40 字节.

2.3 服务类型

服务类型这一属性, 决定了 IP 协议的工作方式.

8 位服务类型中, 其中 3 位优先权字段已经弃用, 还有 4 位 TOS 字段, 和 1 位保留字段(必须置为 0).

所以, 只有其中的 4 位 TOS 字段可供选择, 这 4 个字段分别为:

  1. 最小延时(从 A 到 B, 花费的时间最短)
  2. 最大吞吐量(从 A 到 B, 单位时间内传输的数据量最多)
  3. 最高可靠性(最大程度的降低丢包率)
  4. 最小成本(最大程度的减少系统开销)

并且, 这 4 个字段相互冲突, 只能选择其中一个.

也就是说, IP 协议可以通过设置服务字段中的值, 来切换工作状态, 来优先保证 4 个 TOS 字段中的其中一个性质.(就像迪迦一样, 可以切换速度状态和攻击状态)

2.4 总长度

这一属性, 是 IP 数据报的总长度: 报头 + 载荷.

总长度属性的长度为 16 位, 看到这里, 相信大家就有疑问了, 难道 IP 数据报最多也只能携带 2^16 - 1(65535) 个比特的数据(64KB)??

**虽然一个 IP 数据报能携带的数据量有限, 但是, IP 协议内置了拆包组包的功能(不需要我们手动实现, 它内部就有).**比如: 如果有一个较大的 TCP 数据报, IP 协议就会自动把它拆成多个 IP 数据报, 通过多个 IP 数据报来共同传输一个 TCP 数据报.

2.5 => 16位标识 & 3位标志 & 13位片偏移

这三个属性, 就是为拆包组包而设定的.

2.5.1 => 16 位标识

标识相同, 表示同一组的数据

  • 拆包: 把拆出来的多个包, 设为相同的标识
  • 组包: 把相同标识的数据报, 组合到一起

2.5.2 => 3 位标志

共 3 个比特位, 各比特位含义如下:

  1. DF位(表示是否允许拆包): 1 => 允许分片/拆包; 0 => 不允许分片/拆包
  2. MF位(表示是不是最后一个包): 1 => "后面还有分片"; 0 => "这是最后一个分片"
  3. 保留位: 必须为 0

2.5.3 => 13 位片偏移

描述拆出的各个包的先后顺序.(偏移小的放前面, 偏移大的放后面)

讲到这, 就可以引申出一个面试题:

如果要基于 UDP 实现传输超过 64KB 的数据, 该如何设计??

  1. 思路: 参考 IP 协议的设计.
  2. 既然是基于 UDP, 那么传输层的数据包就是一个 UDP 数据包, 格式已经固定住了(就是 UDP 的格式). 那么我们只能在应用层协议中来设计: 指定标识, 指定标志位, 指定片偏移, 手动写代码来实现拆包组包的功能.

2.6 生存时间(TTL)

表示该 IP 数据包, 能够在网络上传输的最大时间(最大存活时间).

注意: TTL 的单位不是 "时间", 而是 "次数", IP 数据包每经过一次路由器转发, TTL 的值就会 - 1. 当 TTL 的值减到 0 时, 就说明该数据报无法到达目的地址, 就会被丢弃

那 TTL 的作用是什么呢??

  • 比如目的 IP 设置错误时, 即使经过很多次的转发, 也一定不会到达目的地.

我们可以在 cmd 中通过 ping 命令来查看 TTL 值:

上图中 TTL 的初始值为 64, 经过了 11 次转发到达了搜狗服务器.

但是, TTL 的值并不是固定的, 当需要转发的次数较多时, TTL 可以初始化为更大的值: 128, ....

但是, 当地址等一系列信息都设置正确时, 数据报通过这些次数的转发, 就一定能到对端服务器上吗??

理论是可能存在到达不了的情况的, 但是可能性比较小.

  • 因为, 网络中存在 "六度空间" 的理论, 即两台设备之间, 最多通过 6次 转发, 就一定能够到达对端.

啥是 "六度空间" 呢?? 举个例子:

  1. 比如我是一个普通程序员, 我想认识一下特朗普, 那么我就可以向我所有的朋友发起请求, 问问他们认不认识特朗普, 如果他们不认识, 再让他们去问问他们的所有的朋友.......
  • 理论上, 最多通过六层朋友的询问, 我就能认识到特朗普~~ (前提是, 每一层朋友都必须竭尽全力)

在实际生活中, 是很难完成每一层的朋友都竭尽全力的.

但是在网络上, 每个路由器都可以发动他们所有相邻的设备, 于是 "六度空间" 这样的理论是非常可靠的.

2.7 => 8 位协议

标识传输层使用的哪个协议.

分用的使用, IP 协议解析完 IP 数据报头后, 拿到载荷, 交给上层处理. 这里的 8位 协议编号, 就能够起到区分的作用.(交给上层的哪个协议)

  1. 传输层交给应用层, 通过端口号来区分
  2. 网络层交给传输层, 通过 8位 协议编号来区分
  3. 数据链路层交给网络层, 也通过类似的协议编号来区分

2.8 首部校验和

校验 IP 数据报 报头部分的信息是否正确.(不用校验载荷, 载荷部分自有 TCP/UDP 来校验)

2.9 源/目的 IP 地址

这是 IP 协议最重要的部分, 用来标识 源设备和目的设备.

由于 IP 地址由 32 位二进制数构成, 而 32 位不方便阅读, 所以采用 点分十进制 的方式来表示 IP 地址.

3. 地址管理

我们希望 IP 地址用来表示唯一的主机, 而 32 位 IP 地址最多只能表示 42亿9千万 个不同的 IP, 在 15 年前还好, 但是在 2025 年的今天, 这个数字显然早就不够用了...

那么, 是怎样处理 IP 不够用的情况的呢??

  1. 动态分配: 仅对上网的设备分配, 不上网就不分配.(有所缓解, 但治标不治本, 没有从根本上解决问题)
  2. NAT 机制: 网络地址转换 [主力方案]
  3. IPv6 [终极方案]

当前的网络世界, 就是通过 NAT 机制来解决 IP 不够用的问题的.

3.1 动态分配

动态分配: 仅对上网的设备分配 IP 地址, 不上网就不分配.

只是权宜之计, 治标不治本.

3.2 NAT 机制 [主力方案]

那么, NAT 机制的具体实现是怎样的呢??

首先, 把所有的 IP 分成两个大类:

  1. 公网 IP / 外网 IP
  2. 私网 IP / 内网 IP

其中, 公网 IP 是唯一的.

而私网 IP 在不同的局域网中, 可以重复. 以下特定的 IP 地址, 为私网 IP:

  • 10.*
  • 172.16 - 172.31.*
  • 192.168.*

有了以上知识的了解, 我们接下来聊一聊在 NAT 背景下, 网络通信是如何进行的:

  • 情况1: 同一个局域网下, 设备 A 访问设备 B ??

答: 允许访问.

在一个同局域网下, IP 本身就不允许重复, 故通信时不受任何影响, 且 NAT 不起作用, A 和 B 就能正常通信.

  • 情况2: 公网设备 A 访问公网设备 B ??

答: 允许访问.

公网 IP 本身也不允许重复, 故通信也不受影响, 且 NAT 不起作用, A 和 B 就能正常通信.

  • 情况3: 局域网设备 A 访问局域网设备 B ??(不同局域网下)

答: 不允许访问!! NAT 是禁止这样的方式来访问的.

为啥在不同局域网下的两条设备不允许访问呢??

举个例子: 比如我们之前写的 TCP/UDP 回显服务器系统, 我们只能在本机上进行访问, 而别人是无法访问的.

这是因为我们写的服务器的 IP 地址(我们电脑的 IP 地址)是一个内网 IP, 而这个内网 IP 在世界上存在着无数多个, 当目的 IP 的存在不唯一时, 数据包就是不知道要发给谁了, 当然也就无法访问目标设备了~

把我们的电脑设置为内网 IP 的作用是什么??

  1. 其实, 内网 IP 这样的限制, 是对我们的设备进行了保护. 虽然其他人无法访问我们的设备, 但是黑客也无法访问了~
  2. 而如果将我们的电脑设置为公网 IP, 那么任何人都可以访问我们的设备, 这显然存在安全问题.
  • 情况4: 局域网设备 A 访问公网设备 B ??

**答: 允许访问.**使用 NAT 网络地址映射进行访问.

  • 情况5: 公网设备 A 访问局域网设备 B ??

答: 不允许访问!! 除非通过内网穿透或者 VPN(虚拟私人网络) 等特殊手段.****(只能局域网设备主动访问外网设备, 外网设备被动返回响应. 但是外网设备不能主动访问局域网设备)

"内网设备" 可以近似认为处于局域网中, 局域网中的设备具有内网 IP.

"公网设备" 可以近似认为处于广域网中, 广域网中的设备具有公网 IP.

3.2.1 NAT 网络地址映射

那么, 在情况4下(局域网设备 A 访问公网设备 B), NAT 是如何进行网络地址的映射的呢??

假如我的电脑是局域网设备 A, 要访问 MDD 的服务器(公网设备 B), 在请求的传输过程中, 会通过带有公网 IP 的路由器的转发(该路由器具有 NAT 功能).

在路由器转发时, 路由器就会进行 NAT 网络地址的替换: 将请求 IP 数据报中的源 IP(设备 A 的内网 IP)替换为该路由器的公网 IP, 替换完后, 此时数据包中的源 IP 是路由器的公网 IP, 目的 IP 是 MDD 的公网 IP, 都是公网 IP, 就可以进行通信了.

并且, 路由器在进行 NAT 网络地址替换的时候, 会维护一个类似于 "哈希表" 的结构, 将地址替换前后的映射关系记录下来, 这张表称为 NAT 表.

注意: NAT 表中映射的信息不单单是 IP 之间的信息, 而是 IP 和端口号共同组成的信息.(以便给多台设备返回响应时, 能够找到对应的内网 IP)

所以, 公网设备 B 返回的响应报文中的目的 IP 也是该路由器的公网 IP, 而当该响应到达该路由器后, 该路由器会根据 NAT 表中 IP 地址和端口号的信息, 找到对应的内网 IP(局域网设备 A 的内网 IP), 再次进行替换, 将目的 IP(路由器的公网 IP)替换为原先的内网 IP, 最终达到局域网设备 A.

流程图如下:

注意: 数据报在传输的过程中, 是会经过多个 NAT 设备的转发的, 但不一定就会触发 NAT, 只有当 IP 数据报中的源 IP 是内网 IP 时, 才会触发 NAT.

(若是源 IP 是公网 IP, 则说明已经进行了 NAT 替换, 将不会再次触发 NAT)

该路由器中维护的 NAT 表如下:

因此, 局域网中的若干个设备, 共同使用一个公网 IP, 这样可以大大减少 IP 的使用量, 解决了 IP 地址短缺的问题.

(并且现实中, 往往是成千上万个局域网设备共用一个外网 IP).

3.3 IPv6

除 NAT 方案以外, 还有一个终极方案能够解决 IP 地址短缺的问题 --- IPv6.

IPv4 是 4 个字节, 而 IPv6 直接升级到了 16 个字节(128 bit), 能够容纳 2^128 个不同的 IP 地址.

大家可能对 2^128 不敏感, 举个例子, 就算给地球上的每一粒沙子都分配一个 IPv6 地址, 都绰绰有余!!

但是, 目前 IPv6 在世界上的普及成都非常非常的低, 而我国是 IPv6 普及程度最高的国家(没有之一, 约 80% 的覆盖程度).

为啥, IPv6 能够容纳这么多的地址量, 但普及程度这么低呢??

因为 IPv4 换 IPv6 的成本很高, 需要换路由器, 要花很多钱~ 而 NAT 只需升级软件即可, 成本低, 所以 NAT 是目前世界上解决 IPv4 地址短缺的主流方案.

既然 NAT 是主流方案, 那为啥咱国使用 IPv6 呢??

这就上升到国家战略上了, 感兴趣可以观看以下视频.

电子监听、全国断网,棱镜门背后,中国如何从末路狂奔到世界之巅_哔哩哔哩_bilibili

3.4 网段划分

解决完 IP 地址不够用的问题后, 接下来介绍一下 IP 地址中的网段划分规则.

"网段划分" 主要应用于组建网络环境.

3.4.1 网络号和主机号

网段划分, 就是将一个IP 地址划分为两个部分:

  1. 网络号(前半部分)
  2. 主机号(后半部分)

假如有两台设备:

  1. 如果在同一个局域网中, 网络号必须相同, 主机号必须不同.
  2. 如果是在两个相邻的局域网中, 网络号必须不同, 主机号无要求. (如果手动把两个相邻局域网的 IP 网络号设置成一样的, 那么就会导致网络冲突, 网络不通)

路由器具有两个接口(WAN 口和 LAN 口) , 这两个接口有着不同的 IP, 并且处于不同的局域网中, 路由器的功能就是把这两个局域网连接起来, 这样就构成了两个相邻的局域网, 并且他们的网络号必须不同.

3.4.2 子网掩码

对于当前的时代来讲, IP 地址中哪些是网络号, 哪些是主机号, 都是可以手动配置的(不固定).

那么, 给我们一个 IP 地址, 我们该如何判断哪些是网络号, 哪些是主机号呢??

这就需要用到子网掩码了, 子网掩码中, 数值为 1 的部分为网络号, 数值为 0 的部分为主机号:

家用网络的子网掩码一般都为: 255.255.255.0

也可以将 IP 地址写为: 192.168.1.6/24 (表示前 24 位为网络号)

子网掩码, 是当前时代网段划分的方式.

而在 "远古时期" 的分类编址方式下是没有子网掩码的(它明确规定了哪些位是网络号, 哪些位是主机号):(开发中用不到, 学校考试会考~)

3.5 特殊的 IP 地址

有以下三种特殊的 IP 地址:

  • IP 地址中的主机号全部设为 0 时, 表示当前局域网的网络号, 代表这个局域网 => 192.168.1.0
  • IP 地址中的主机号全部设为 1 时, 表示广播地址 => 192.168.1.255
  • 127.* 的 IP 地址表示环回 IP, 用于测试, 习惯上通常为 127.0.0.1 (不管你本机的真实 IP 为多少, 127.0.0.1 都可以代表本机)

啥叫广播地址呢??

上面说了, 主机号全为 1 时, 为广播地址.

当一个数据报的目的地址为广播地址时 , 就会给所在局域网所有的设备都发送该数据报.

举个例子:

当我们使用手机往电视上投屏时, 手机就会搜索所有能够投屏的设备(前提是在同一个 WiFi 下, 也就是同一个局域网中), 然后我们就可以选择我们想要投屏的设备了.

这里手机搜索的过程, 就是在向局域网中的设备发送广播地址的请求, 询问哪个设备能投屏.

注意: 广播地址只能通过 UDP 来进行传输, TCP 是不能广播的.

除了上述的特殊 IP 之外, 我们还有一个习惯用法:

  • 将主机号设为 1, 表示网关 IP => 192.168.1.1 (只是习惯用法, 并非强制)

网关, 就是网络的出口/入口.

家庭中, 网关就是指路由器; 大型企业/网络结构 中, 网关通常是单独的设备.


4. 路由选择

路由选择是 IP 协议的第二个主要工作, 就是通过 IP 协议, 进行数据的转发工作.

路由器的路由选择, 采用的是 启发式/探索式 的方式, 简单来说就是 "问路的方式".

什么是 "问路的方式" 呢??

举个例子:

我要去一个很远的地方(假设没有导航), 我不知道咋走, 我就会向别人问路, 而由于路程太复杂了, 我一下子记不住咋走, 所以每次我只能记住一点, 而每到一个地方我就会再问路, 一点一点的接近目的地.

路由器的路由选择也是一样的, 由于网络上的情况太复杂了, 路由器无法一下存储所有的网络信息, 只能记住和它相连的网络的情况.

而当数据报到达一个路由器时, 就会去匹配这个路由器的 "路由表"(路由表中记录了该路由器周围设备的 IP, 以及每台设备要从路由器的哪个接口转发出去):

  1. 如果该数据报的目的 IP 在路由表中有记录, 则直接按照对应的接口的转发出去
  2. 如果目的 IP 没有在路由表中记录, 则会将该数据报转发给路由表中 "下一跳" 指向的设备("下一跳" 是路由表中的特殊表项, 指向的是上一级路由器所在的位置)

路由器越往上, 涵盖的范围就越广, 存在数据报目的 IP 的记录的概率就越大.

注意: 在路由表中进行 IP 地址的匹配时, 匹配的不是精确相等, 而是 IP 的部分网段.

至于路由表是咋来的, 路由表的具体内容是啥, 以及路由表背后广域网的网络架构是啥, 作为 Java 开发来讲就不必深入学习了(本篇文章仅为简单讨论)~


++END++

相关推荐
癞皮狗不赖皮12 分钟前
WEB攻防-通用漏洞_XSS跨站_MXSS_UXSS_FlashXSS_PDFXSS
网络·安全·web安全·xss
比特在路上30 分钟前
初阶数据结构【队列及其接口的实现】
c语言·开发语言·数据结构
多多*34 分钟前
JUC Java并发编程 高级 学习大纲 动员
java·开发语言·学习·面试·架构·bash·intellij-idea
wclass-zhengge1 小时前
01基本介绍篇(D2_多线程问题)
开发语言·python
路星辞*2 小时前
ssl与ipsec的区别
运维·网络·网络协议·ssl·ipsec
不知名美食探索家2 小时前
【9.1】Golang后端开发系列--Gin快速入门指南
开发语言·golang·gin
qq_243050792 小时前
Thc-Ipv6攻击工具包 全参数详细解析!Kali Linux入门教程!黑客渗透测试!
linux·运维·网络·安全·web安全·网络安全·系统安全
云计算DevOps-韩老师2 小时前
【网络云SRE运维开发】2025第3周-每日【2025/01/14】小测-【第13章ospf路由协议】理论和实操
网络·智能路由器·运维开发
Yang-Never2 小时前
Shader -> BitmapShader贴图着色器详解
android·开发语言·kotlin·android studio·贴图·着色器
代码对我眨眼睛2 小时前
重回C语言之老兵重装上阵(一)vscode编译.C文件
c语言·开发语言·vscode