UNP_12_IPv4和IPv6的互操作性
12.1 概述
未来,因特网会逐渐从 IPv4 转换到 IPv6,所以引用程序能够对两种协议协同工作是很重要的,我们将讨论 IPv4 应用如何与 IPv6 进行通信
12.2 IPv4 客户与 IPv6 服务器
双栈主机一个很重要的特性就是技能处理 IPv4 又能处理 IPv6 客户。这是通过使用 IPv4 映射的 IPv6 地址来实现的 主机使用 IPv6 服务器,收到 IPv4 的帧时,会将源 IPv4 地址转换为一个映射的 IPv6 地址 一个 IPv4 客户端和 IPv6 服务端通信地步骤如下:
- IPv6 服务器启动后创建一个 IPv6 监听套接字
- IPv4 客户调用 getsockname 找到服务器地 A 记录。服务器既有 A 也有 AAAA 记录,因为它是双栈的
- 客户调用 connect,发送一个 IPv4 的 SYN 给服务器
- 服务器收到这个 SYN,把它标志为 IPv4 映射为 IPv6,响应一个 IPv4 SYN/ACK。连接建立后,由 accept 返回给服务器的地址就是这个 IPv4 映射的 IPv6 地址
- 当服务器向这个客户端发送数据时,会使用客户端的 IPv4 地址,所以通信使用的全部都是 IPv4 连接
- 如果服务器不检查这个地址时 IPv6 还是 IPv4 映射过来,它永远不会知道客户端的 IP 类型,客户端也不需要知道服务器的类型
大多数双栈主机遵循以下规则:
- IPv4 监听套接字只能接受来自 IPv4 客户的外来连接
- 如果服务器有一个绑定了 IPv6 的监听套接字,该套接字没设置 IPV6_V6ONLY 套接字选项,它可以接收 IPv4 连接
- 如果服务器有一个 IPv6 监听套接字,绑定了通配地址,该套接字设置了 IPV6_V6ONLY 套接字选项,它只能接收 IPv6 连接
12.3 IPv6 客户与 IPv4 服务器
客户机运行在双栈主机上并使用 IPv6 套接字描述符
- 一个 IPv4 服务器在只支持 IPv4 的主机上启动一个 IPv4 监听套接字
- IPv6 客户启动后调用 getaddrinfo 单纯查找 IPv6 的地址,因为服务器只支持 IPv4,所以返回给客户端的是一个 IPv4 映射的 IPv6 地址
- IPv6 客户在作为函数参数的 IPv6 套接字地址结构中设置这个 IPv4 映射的 IPv6 地址然后调用 connect。内核检测到这个映射地址后自动发送一个 IPv4 SYN 到服务器
- 服务器响应一个 IPv4 SYN/ACK,连接于是通过使用 IPv4 数据报建立
12.4 IPv6 地址测试宏
有一些 IPv6 应用必须知道和它通信的是 IPv6 还是 IPv4 协议,使用 <netinet/in.h> 中的函数可以进行测试
12.5 源代码可移植性
考虑到源码的可移植性,编写代码时应尽量避免 gethostbyname gethostbyaddr 等套接字函数,使用 getaddrinfo getnameinfo 等函数,使得代码变得与协议无关。
小结
- 双栈主机的 IPv6 服务器可以和两种客户端进行通讯,网络中仅使用 IPv4 进行传输
- 双栈主机的 IPv6 客户端也可以和两种服务器进行通讯