Loading

《Unix 网络编程》12:IPv4 和 IPv6 的互操作性

IPv4 和 IPv6 的互操作性

系列文章导航:《Unix 网络编程》笔记

IPv4客户端与IPv6服务器

IPv4 Mapped IPv6 address

双栈主机的一个基本特性是其上的 IPv6 服务器既能处理 IPv4 客户,又能处理 IPv6客户,这是通过使用 IPv4 映射的 IPv6 地址实现的:

例如:

graph LR; A("206.52.225.32") --映射为IPv6--> B("::FFFF:206.52.225.32")

通信的流程

(以TCP为例)关键步骤是:

  • 接收端的数据链路通过查看以太网类型字段把每个帧传递给相应的 IP 模块。IPv4 模块结合其上的 TCP 模块检测到 IPv4 数据报的目的端口对应的是一个 IPv6 套接字,就把该数据报 IPv4 首部中的源 IPv4 地址转换成一个等价的 IPv4 映射的 IPv6 地址
  • 当服务器发送 TCP 分节时,目的地址为所映射 IPv4 地址的 IPv4 载送数据报

总结

  • 因此等于是这些底层模块向上提供了一种抽象,使得 IPv6 服务器无需关心向自己发起请求的是 IPv4 还是 IPv6,具体的转换工作是由下层来做的
  • 除非服务器显式检查这个 IPv6 地址是不是一个 IPv4 映射的 IPv6 地址(使用后文介绍的 IN6_IS_ADDR_V4MAPPED),否则它永远不知道其是 IPv4 还是 IPv6
  • UDP 也有类似的机制
  • 反过来则不行,不能将 IPv6 地址映射为 IPv4 地址

IPv6客户端与IPv4服务器

这里的假设前提是:

  • 客户端是一个运行双栈的 IPv6 客户
  • IPv6 客户启动后调用 getaddrinfo 单纯查找 IPv6 地址,并在 hints 中设置了 AI_V4MAPPED 标志(见11章)

总结

  • 与上文相似,这里是由底层模块向上提供了一种抽象,使得 IPv6 客户无需关心自己发起请求的目标是 IPv4 还是 IPv6,具体的转换工作是由下层来做的
  • 同样,反过来不行,IPv4 客户不能向 IPv6 服务器发起请求

对互操作性的总结

如图所示:

  • 加星号的表示如果客户端选用 IPv4 地址就可以工作
  • 在可见的未来,双栈会很普及,所以如果我们把图中的红色部分去除,会发现几乎都可以通信

地址是否是映射的 IPv6

一小类的 IPv6 应用必须清楚与其通信的是不是 IPv4 对端,是不是经过映射的 IPv6 地址,可以用如下的宏解决:

#include <netinet/in.h>


前七个宏用来测试 IPv6 地址的基本类型

后五个宏测试 IPv6 多播地址的范围

一个例子:

FTP 客户端通过控制连接向服务器发送 PORT 指令,以让服务器建立一个数据连接

PORT 指令需要根据服务器的 IP 版本决定发送的指令的具体格式

posted @ 2022-05-28 10:40  樵仙  阅读(121)  评论(0编辑  收藏  举报