128 位写成八组四位十六进制,用冒号分隔。 两条省略规则:前导零可省、连续零组用「::」,但「::」只能出现一次。
4.3.1 讲过 IPv4 的写法,这里换成 IPv6 的。 4.6.4 会讲地址内部怎么划分,先学会「怎么把一个地址写对」。
一、基本写法:八组十六进制
128 位除以 16 等于 8,所以是八组。 每组四位十六进制,范围 0000 到 ffff。
| 项 | IPv4 | IPv6 |
|---|---|---|
| 进制 | 十进制 | 十六进制 |
| 分隔符 | 点 | 冒号 |
| 组数 | 4 组 | 8 组 |
| 一组几位 | 8 位 | 16 位 |
第三行「8 组」是硬规定: 展开写法必须凑满八组,缺的补零——这一点在「把压缩写法还原」时特别重要。
二、两条省略规则
规则一:每组前面的零可以省。 0001 写成 1,00ab 写成 ab,0000 写成 0。 规则二:连续的全零组可以用「::」一次代替。 注意是「连续」且「只能一次」。
| 完整写法 | 压缩后 | 省在哪儿 |
|---|---|---|
| 2001:0db8:0000:0000:0000:ff00:0042:8329 | 2001:db8::ff00:42:8329 | 前导零 + 三组零 |
| fe80:0000:0000:0000:0202:b3ff:fe1e:8329 | fe80::202:b3ff:fe1e:8329 | 同上 |
| 0000:0000:0000:0000:0000:0000:0000:0001 | ::1 | 七组零 |
三行都同时用了两条规则:先省前导零,再把连续零换成 ::。 顺序不能反——先换 :: 的话,剩下的组就没法数了。
三、为什么「::」只能一次
因为「::」代表「若干组零」,而组数必须是 8。 如果出现两个「::」,就没法算出每个代表几组。
| 写法 | 能不能还原 | 原因 |
|---|---|---|
| 2001:db8::1:0:0:1 | 能 | 一个 :: 代表 2 组 |
| 2001:db8::1::1 | 不能 | 两个 :: 算不清 |
第一行那个例子很典型: 原地址是 2001:0db8:0000:0000:0001:0000:0000:0001,有两段连续零,但只能压前一段, 后一段老老实实写成 0:0。 所以压缩结果看着有点怪,但它是对的。 还原的办法是「数剩下的组」:八组减去已经写出来的组数,剩下的就是 :: 代表的组数。 这也是为什么「::」不能一次用两个。
四、前缀长度怎么写
和 IPv4 一样用斜杠:2001:db8::/32。 但含义要清楚:/32 指的是「前 32 位是网络部分」。
| 写法 | 含义 | 谁用 |
|---|---|---|
| 2000::/3 | 全球单播的总范围 | 协议规定 |
| 2001:db8::/32 | 文档示例专用 | 写书、写文档 |
| fd00::/8 | 唯一本地地址 | 内网 |
| fe80::/10 | 链路本地地址 | 同一链路 |
第二行那个 2001:db8::/32 要记牢:它是 IANA 专门留给「文档和例子」的, 不会和真实网络冲突。 所以看到教程里用这个地址,说明作者是守规矩的。
五、动手 Demo:IPv6 地址怎么写才不啰嗦
用 ipaddress 把几种写法压缩、再展开,看省略规则到底怎么生效。
注意第三行那个「压一半」的结果:2001:db8::1:0:0:1。
import ipaddress
for s in ('2001:0db8:0000:0000:0001:0000:0000:0001',
'fe80:0000:0000:0000:0202:b3ff:fe1e:8329',
'0000:0000:0000:0000:0000:0000:0000:0001'):
a = ipaddress.IPv6Address(s)
print(a.compressed, a.exploded.count(':') + 1)
实跑输出:
--------------------------------------------------------------------
IPv6 地址怎么写才不啰嗦
--------------------------------------------------------------------
**128 位写成 8 组十六进制太长了**,
**所以有两条省略规则:前导零可以省、连续的全零组可以用「::」代替。**
**注意「::」只能出现一次**——否则就没法还原成 8 组了。
完整写法 压缩后
---------------------------------------------------------------------
2001:0db8:0000:0000:0000:ff00:0042:8329 2001:db8::ff00:42:8329
fe80:0000:0000:0000:0202:b3ff:fe1e:8329 fe80::202:b3ff:fe1e:8329
2001:0db8:0000:0000:0001:0000:0000:0001 2001:db8::1:0:0:1
0000:0000:0000:0000:0000:0000:0000:0001 ::1
0000:0000:0000:0000:0000:0000:0000:0000 ::
**第三行是关键**:**有「两段全零」,只压了前一段(变成 ::),后一段保留成 0:0。**
**因为再压一次就没法判断「::」代表几组零了。**
**反过来,压缩写法也能展开回 8 组**:
压缩写法 展开 组数
----------------------------------------------------------------
::1 0000:0000:0000:0000:0000:0000:0000:0001 8
fe80::1 fe80:0000:0000:0000:0000:0000:0000:0001 8
2001:db8:: 2001:0db8:0000:0000:0000:0000:0000:0000 8
**最后一列永远是 8**——**这就是「只能压一处」的原因:组数是固定的。**
**还有一条容易踩的**:**「::」和「::1」不是一回事,前者是全零地址(未指定),后者是回环。**
**写配置时少一个 1,行为完全不同。**
compressed 和 exploded 是一对:一个给「最短写法」,一个给「完整的八组」。
写配置用前者,做解析和比较用后者。
第三行那个结果为什么只压了前一段:ipaddress 的实现是「找最长的一段连续零」,
两段一样长时取靠前的。所以它压前面那段,后面保留 0:0。
这不是 bug,是 RFC 允许的自由选择。
第二张表的「组数永远是 8」是最实用的自检手段:
拿到一个压缩地址,展开数一下是不是 8 组,就知道它有没有写错。
命令行里 ping6 报「地址不合法」时,先数这个。
30 秒实验
- 写出 2001:db8:0:0:1:0:0:1 压缩后的样子。
- 想一下:为什么「::」不能出现两次?
- 算一下:fe80::1 展开后有几个 0?
常见误区
- 以为「::」可以随便用几次。 只能一次,否则无法确定每组零代表几位。
- 以为「前导零不能省」。 可以省,0001 就是 1。
- 以为「2001:db8:: 是真实地址」。 是文档专用段,专门给例子用。
自测三问(点开对答案)
1. IPv6 地址由几组十六进制组成? —— **八组**,每组 16 位,加起来 128 位。 2. 「::」的两条限制是什么? —— **只能出现一次,而且只能代表连续的全零组。** 3. 2001:db8::/32 是干什么用的? —— **文档和示例专用**,不会与真实网络冲突。下一节拆开看:这 128 位内部是怎么划分的。
- ☐ (本节完,下一节 4.6.4 IPv6地址的结构)