1. 前戏
IPv6 的普及已经喊了很多年了, 但是事与愿违啊, 由于 NAT 技术的出现, 硬是将当时岌岌可危的 IPv4 拖了二十年, 所谓的普及 IPv6 还是遥遥无期, 不可否认 NAT 技术真的很伟大, 但是 IPv6 肯定是未来的趋势, 作为网络编程的开发人员, 系统的详细的了解 IPv6 还是很有必要的. 我相信 IPv6 的普及很快就会到来, 身怀此绝技的读者你们, 肯定是香馍馍了. 所以开始看文章吧.
其实我们用的比较多的主流操作系统都已经支持了 IPv6 协议栈, Windows7,Linux2.6 之后的版本等等.
2. IPV6 的基本概念
周所周知, IPv6 采用 128 位的地址长度拥有更大的地址空间. 首先我们先来认识一下 IPv6 到底长成什么样子.
IPv6 数据报文和 IPv4 有很大的差别:
数据链路层 (L2) 的 type 字段标识为 0x86dd, 表示承载的上层协议是 IPv6(IPv4 对比: type 字段为 0x0800);
IPv6 的头部字段, 和 IPv4 差别巨大(可以猜测到, IPv6 和 IPv4 无法兼容).
我们来看下 ipv6 的报文头部格式:
Ipv6 报文头部
ipv6 的头部更加的简单, 少了很多的字段, 对比 ipv4, 有这几个地方需要注意:
IPv6 报文头部是定长(固定为 40 字节),IPv4 报文头部是变长的. 这个意味着, 写代码处理 IPv6 数据报文的效率会提高很多:);
IPv6 中 Hop Limit 字段含义类似 IPv4 的 TTL;
IPv6 中的 Traffic Class 字段含义类似 IPv4 中的 TOS(Type Of Service);
IPv6 的报文头部取消了校验和字段: 取消这个字段也是对 IPv4 协议的一个改进. 当 IPv4 报文在网路间传输, 每经过一个路由器转发就是修改 TTL 字段, 就需要重新计算校验和, 而由于数据链路层 L2 和传输层 L4 的校验已经足够强壮, 因此 IPv6 取消这个字段会提高路由器的转发效率. 值得一提的是, 在 IPv6 协议下, 传输层 L4 协议 UDP,TCP 是强制需要进行校验和的(IPv4 是可选的);
IPv6 报文头部中的 Next Header 字段表示 "承载上一层的协议类型" 或者 "扩展头部类型".
这里的含义与 IPv4 有很大的差别, 需要加以解释:
当 IPv6 数据报文承载的是上层协议 ICMPv6,TCP,UDP 等的时候, Next Header 的值分别为 58,6,17, 这个时候和 IPv4 报文头部中的 Protocol 字段很类似;
当不是以上 3 种协议类型的时候, IPv6 报文头部紧接的是扩展头部. 扩展头部是 IPv6 引入的一个新的概念, 每个 IPv6 的数据报文可以承载 0 个或多个扩展头部, 扩展头部通过链表的形式组织起来. 当 IPv6 数据报文承载着扩展头部的时候, Next Header 的数值为扩展头部的类型值.
为什么要引入扩展头部这个概念, 这里也是 IPv6 对 IPv4 改进的一个方面, 用扩展头部取代了 IPv4 的可选项信息, 精简了 IPv6 的头部, 增强了 IPv6 的扩展性. 有同学会不会有疑问, IPv6 的分片数据报文怎么处理? 其实就是使用了 IPv6 扩展头部.
当发送一个分片 IPv6 数据报文的时候, IPv6 使用的是扩展头部的形式组织各个分片的信息, IPv6 报文头部 Next Header 字段值为 44 表示存在扩展头部, 扩展头部是 IPv6 分片数据信息.
对比 IPv4, 分片信息是记录在 IPv4 报文头部的分片字段中.
IPv6 的扩展头部类型有很多种, 除了上述的分片头部, 还有路由头部, 逐跳可选头部等, 具体的可以参考 RFC2460.
本章主要介绍了 IPv6 的一些很直观的认识, 下面逐渐介绍 IPv6 上的基本知识和概念.
3. ipv6 的地址语法
一个 IPv6 的地址使用冒号十六进制表示方法: 128 位的地址每 16 位分成一段, 每个 16 位的段用十六进制表示并用冒号分隔开, 例如:
一个普通公网 IPv6 地址:
2001:0D12:0000:0000:02AA:0987:FE29:9871
IPv6 地址支持压缩前导零的表示方法, 例如上面的地址可以压缩表示为:
200112:0:0:2AA:987:FE29:9871
为了进一步精简 IPv6 地址, 当冒号十六进制格式中出现连续几段数值 0 的位段时, 这些段可以压缩为双冒号的表示, 例如上面的地址还可以进一步精简表示为:
[pquote]200112::2AA:987:FE29:9871
又例如 IPv6 的地址 FF80:0:0:0:FF:3BA:891:67C2 可以进一步精简表示为:
FE80::FF:3BA:891:67C2
这里值得注意的是: 双冒号只能出现一次.
4. IPv6 地址的号段划分和前缀表示法
IPv6 拥有 128 位巨大的地址空间, 对于那么大的空间, 也不是随意的划分, 而是使用按照 bit 位进行号段划分(与鹅厂内部一些的 64 位 uin 改造放号的 zone 划分算法).
IPv6 的地址结构如下图:
例如 RFC4291 中定义了 n=48, m=16, 也就是子网和接口 ID 与各占 64 位.
IPv6 支持子网前缀标识方法, 类似于 IPv4 的无分类域间路由 CIDR 机制(注意: IPv6 没有子网掩码 mask 的概念).
使用 "IPv6 地址 / 前缀长度" 表示方法, 例如:
2001:C3:0:2C6A::/64 表示一个子网;
而 2001:C3:0:2C6A:C9B4:FF12:48BC:1A22/64 表示该子网下的一个节点地址.
可以看到, 一个 IPv6 的地址有子网前缀 + 接口 ID 构成, 子网前缀由地址分配和管理机构定义和分配, 而接口 ID 可以由各操作系统实现生成, 生成算法后面的章节会介绍.
5. IPv6 的地址类型
IPv6 地址分三种类型:
单播, 对应于 IPv4 的普通公网和私网地址;
组播, 对应于 IPv4 的组播 (多播) 地址;
任播, IPv6 新增的地址概念类型.
IPv6 没有广播地址, 用组播地址实现广播的功能. 实际上我们工作和生活最可能最多接触的就是单播地址, 接下来本文重点会讲解单播地址的种类. 组播和任播地址有兴趣的同学自行查阅相关 RFC 和文献.
来源: http://network.51cto.com/art/201808/580997.htm