写在前面
前几篇走完了分层模型、链路层,又把网络层的 IP 数据报整体结构(头部字段、TTL 的作用)过了一遍。这一篇聚焦 IP 协议里被引用最多、面试最爱考、工程上最常踩坑的部分:IP 地址到底怎么编排、子网怎么划分、路由器怎么查表转发,以及 ICMP 怎么撑起 ping 和 traceroute 。
这些知识在云原生里天天见——配置 Pod 的 CIDR、规划 VPC 子网、写路由表、排查"为什么 ping 不通",全靠它。
一、IPv4 地址:32 位与点分十进制
IPv4 地址是一个 32 位的无符号整数,为了方便记忆,把它每 8 位切一段、转成十进制、用点连起来,这就是"点分十进制":
| |
所以 IPv4 地址总共只有 2³² = 4294967296(约 43 亿)个,这正是地址紧缺、要搞 IPv6 和 NAT 的根本原因。
注意 IP 地址是网络层地址,跨网可路由;而 MAC 地址是链路层地址,只在同一链路内有效。这两套地址体系互不替代,后面讲 ARP 会把它们接起来。
二、网络位与主机位:地址的两段结构
光知道 32 位还不够,关键在于这 32 位要拆成两段:
| |
- 网络位(network prefix) —— 决定这个地址属于哪个网段,路由器逐跳转发时只看这部分;
- 主机位(host part) —— 在同一网段内区分不同主机,只有"到了最后一跳、进了目的网络"之后才用得上。
历史上有 A/B/C 三类地址,靠固定的前几位决定网络位长度(A 类 /8、B 类 /16、C 类 /24)。但这种"定长分类"太死板:一个 /16 网段有 65534 个主机地址,对一个几十台机器的小公司是巨大浪费;一个 /252 又装不下大企业。于是有了子网划分和 CIDR(无类别域间路由)——网络位长度不再由"类别"决定,而是可以任意指定。
三、子网掩码与 CIDR 记法
既然网络位长度可变,就需要一种方式告诉别人"前多少位是网络位"。有两种等价写法:
1. 子网掩码(dotted mask) —— 把网络位全置 1、主机位全置 0,也写成点分十进制:
| |
2. CIDR 记法 —— 在 IP 地址后面直接写 /n,n 就是网络位的位数:
| |
工程里几乎都用 CIDR 记法,因为它一眼就能看出网络位长度。常见的 CIDR 与掩码对应:
| CIDR | 子网掩码 | 主机位 | 可用主机数 | 典型用途 |
|---|---|---|---|---|
| /8 | 255.0.0.0 | 24 | 16777214 | A 类整段、10/8 私有 |
| /16 | 255.255.0.0 | 16 | 65534 | 中型网络、172.16/12 子段 |
| /24 | 255.255.255.0 | 8 | 254 | 最常见的子网大小 |
| /28 | 255.255.255.240 | 4 | 14 | 小网段、云上分配合 |
| /30 | 255.255.255.252 | 2 | 2 | 点对点链路 |
| /32 | 255.255.255.255 | 0 | 1 | 单机路由、主机精确匹配 |
两个特例:可用主机数 = 2^(主机位) − 2 ,因为主机位全 0 的那个是"网络地址"、全 1 的那个是"广播地址",都不能分配给主机。/31 是个特殊例外(RFC 3021),点对点链路上只有两台主机、不需要广播,所以两个地址都可用;/32 则表示单个主机,没有主机位。
四、动手算:网络地址、广播地址、可用主机数
这是面试高频题,也是规划子网的基本功。规则只有三条:
- 网络地址 = IP 地址 AND 子网掩码(按位与,主机位清零);
- 广播地址 = 网络地址 OR (主机位全 1);
- 可用主机数 = 2^(主机位) − 2,范围是"网络地址 + 1"到"广播地址 − 1"。
例 1:192.168.1.10/24
| |
例 2:10.0.0.5/22(非字节边界,更接近真实场景)
| |
第二个例子最容易出错的地方是第 3 字节的边界:掩码 252 说明第 3 字节里只有前 2 位属于网络位,后 2 位属于主机位。所以广播地址的第 3 字节是 00000000 | 00000011 = 3,整个网段横跨 10.0.0.0 ~ 10.0.3.255 这四个"第 3 字节"。
一个速算技巧:对 /24 以上(即掩码在第 4 字节内)的子网,“块大小”= 256 − 掩码字节。比如 /28 掩码是 .240,块大小 = 256 − 240 = 16,所以子网的第 4 字节从 0 开始按 16 递增:.0、.16、.32……这台主机落在哪个块里,网络地址就是那个块的起点。
五、VLSM 与私有地址段
VLSM:可变长子网掩码
CIDR 让网络位长度任意,而 VLSM(Variable Length Subnet Masking,可变长子网掩码) 进一步允许对同一个主网,按不同子网的实际大小切出不同掩码长度。
举个规划例子:一个公司拿到 192.168.10.0/24,要分给几个不同规模的部门:
| |
没有 VLSM 之前(只能用定长子网掩码 FLSM),所有子网都得按最大的那个来切,地址浪费严重。VLSM 让掩码长度"按需伸缩",是现代网络和云上 VPC 子网规划的基础。
私有地址段(RFC 1918)
不是所有地址都能在公网路由。RFC 1918 划出三段私有地址,供内网自由使用、不用申请,出公网时靠 NAT 转换:
| 名称 | 网段 | CIDR | 容量 |
|---|---|---|---|
| A 类私有 | 10.0.0.0 ~ 10.255.255.255 | 10.0.0.0/8 | 2²⁴(约 1677 万) |
| B 类私有 | 172.16.0.0 ~ 172.31.255.255 | 172.16.0.0/12 | 2²⁰(约 100 万) |
| C 类私有 | 192.168.0.0 ~ 192.168.255.255 | 192.168.0.0/16 | 2¹⁶(65536) |
家里路由器的 LAN、公司办公网、数据中心内网、云上 VPC、Docker 默认网桥——绝大多数内网都落在这三段里。还有几个特殊段也值得知道:169.254.0.0/16(链路本地,DHCP 拿不到地址时的 fallback)、127.0.0.0/8(环回,localhost)。
六、路由表与最长前缀匹配
IP 地址规划好之后,路由器靠"路由表"决定每个包往哪转发。一条路由条目至少包含三要素:
| |
比如一台主机的路由表可能长这样:
| |
最长前缀匹配(Longest Prefix Match)
当一个目的地址能匹配多条路由时,路由器永远选掩码最长(最具体)的那条——因为掩码越长、网络位越精确,指向的网段越小。
举例:要发往 10.0.0.50,路由表里有 10.0.0.0/22 和 10.0.0.0/24 两条。两者都能匹配(50 落在这两个网段里),但 /24 比 /22 更长更具体,于是走 /24 那条。
| |
默认路由与默认网关
如果没有任何具体路由能匹配目的地址怎么办?交给默认路由 0.0.0.0/0。它的掩码是 0 位,能匹配任意地址,所以它是"兜底"——按最长前缀匹配规则,它永远排在最后才被选中。
家宽场景里,主机的默认路由下一跳就是默认网关(家用路由器的 LAN 口 IP),所有"非本网段"的流量都甩给它,由它继续往运营商转发。ip route 或 route -n 看到的 default via ... 就是这条。
| |
七、ICMP:ping 与 traceroute 的底层
IP 协议本身只管"尽力把包送到",不反馈任何状态。ICMP(Internet Control Message Protocol,互联网控制报文协议) 就是 IP 层的"信使",用来报告差错和探测网络——ping 和 traceroute 都建立在它之上。
严格说 ICMP 工作在网络层(和 IP 同层,封装在 IP 包里,协议号 1),没有端口号,不涉及传输层。所以"ping 某个端口"在 ICMP 意义上是不成立的——ping 只能测主机可达性。
ping:Echo Request / Echo Reply
ping 的原理极其简单——发一个 ICMP Echo Request(类型 8,代码 0) 给目标,目标收到后回一个 Echo Reply(类型 0,代码 0),一来一回就能算 RTT 和丢包:
| |
ping 不通的原因很多:目标离线、路由不可达、防火墙丢弃了 ICMP(很多生产环境出于安全只放行业务端口、禁 ping,所以"ping 不通 ≠ 服务不可用",这点排查时要记牢)。
traceroute:靠 TTL 递增一跳跳摸路径
traceroute 巧妙利用了 IP 头部里的 TTL(Time To Live,生存时间) 字段。每经过一台路由器,TTL 减 1;一旦减到 0,路由器就丢弃该包并回送一个 ICMP Time Exceeded(类型 11) 给源。traceroute 正是靠这个回包"自报家门"的:
| |
过程是:先发 TTL=1,第一台路由器把 TTL 减到 0、回 Time Exceeded,于是知道了第一跳;再发 TTL=2,第二台路由器回包,知道第二跳……如此递增,直到某个探测包真正到达目标,目标回一个应答(ICMP Echo Reply 或 UDP 端口不可达),路径就摸完了。
一个跨平台要注意的细节:探测包用什么协议,不同系统不一样——
- Linux 的
traceroute(传统默认)发 UDP 探测包,目的端口用一个递增的高端口,目标通常因端口未监听而回 ICMP Port Unreachable(类型 3); - Windows 的
tracert发 ICMP Echo Request 探测包,目标回 Echo Reply。
两者定位每一跳都靠中间路由器回的 ICMP Time Exceeded(类型 11),只是"到达目标后收到的那个结束应答"不同。现代 Linux 也可以用 traceroute -I 强制走 ICMP、mtr 做持续式路径探测,在排查抖动时更顺手。
小结
- IPv4 地址是 32 位整数,点分十进制只是写法;核心在于它被切成网络位 + 主机位 ;
- 子网掩码和 CIDR
/n是描述网络位长度的两种等价方式,可用主机数 = 2^(主机位) − 2; - 网络地址 = IP AND 掩码,广播地址 = 主机位全 1;非字节边界(如 /22)的算法要练熟;
- VLSM 让同一主网按需切出不同掩码;私有地址段(10/8、172.16/12、192.168/16)供内网自由使用;
- 路由器按最长前缀匹配选路,默认路由 0.0.0.0/0 是兜底;
- ICMP 是 IP 层信使,ping 用 Echo Request/Reply 测可达性,traceroute 靠 TTL 递增 + Time Exceeded 逐跳摸路径。
下一篇:TCP/IP(五):传输层与 UDP —— 从"主机到主机"上升到"进程到进程",讲清端口号、套接字,以及 UDP 这个"极简"传输层协议的头部、校验和和适用场景。
参考: