IPv4 和 IPv6的互操作性

时间:2023-01-29 22:06:48
IPv4客户与IPv6服务器通信
步骤如下:

    1、IPv6服务器启动后创建一个IPv6监听套接字,我们假定服务器把通配地址绑定到该套接字
    2、IPv4客户调用gethostbyname找到服务器的A记录(IPv4地址)。服务主机既有一个A记录,也有一个AAAA记录(IPv6地址),因为它同时支持IPv6和IPv4,不过客户只需要A记录
    3、客户调用connect,导致客户发送一个IPv4 SYN到服务器
    4、服务器接收这个目的地址为IPv6监听套接字的IPv4 SYN,设置一个标志指示本连接应该使用IPv4映射的IPv6地址,然后响应一个 IPv4 SYN/ACK。连接建立后,由accept返回给服务器的地址即为这个IPv4映射的IPv6的地址
    5、当服务器主机往这个IPv4映射的IPv6地址发送TCP分节时,其IP栈产生目的地址为所映射IPv4地址的IPv4载送数据报。因此,客户与服务器之间所有通信都是IPv4的载送数据报
    6、除非这个服务器显式的检查这个IPv6地址是不是一个IPv4地址映射的IPv6地址(IN6_IS_ADDR_V4MAPPED),否则它永远不知到自己其实是在和一个IPv4客户通信,同样的,客户也不知道自己是和一个IPv6服务器在通信
        (上述情形的一个支撑性假设是,双栈服务器主机既有一个IPv4地址,又有一个IPv6地址。在所有IPv4耗尽前,这个假设没问题)    


    如果收到一个目的地为某个IPv6套接字的IPv4数据报,那么内核把与该数据报的源IPv4地址对应的IPv4映射的IPv6地址作为由accept或recvfrom返回的对端IPv6地址(映射是可行的,因为任何IPv4总能表示成一个IPv6地址。客户和服务器之间交换的是IPv4数据报)
    相反却不能成立,因为一般来说, 一个IPv6无法表示成一个IPv4地址


大多双栈主机在处理监听套接字时应使用如下规则:
    1、IPv4套接字只能接收来自IPv4客户端的外来连接
    2、一个IPv6套接字,如果设置了IPV6_V6ONLY,那么只能接收来自IPv6客户的连接请求



IPv6客户与IPv4服务器通信
步骤如下:

    1、一个IPv4服务器在只支持IPv4的一个主机上启动后创建一个IPv4套接字
    2、IPv6客户启动后调用getaddrinfo单纯的查找IPv6地址。既然只支持IPv4的服务器只有A记录,那么返回给客户的是一个IPv4映射的IPv6地址
    3、IPv6客户设置这个IPv4映射的IPv6地址调用connect,内核检测到这个映射地址后自动发送一个IPv4 SYN到服务器
    4、服务器响应一个IPv4 SYN/ACK到客户,连接于是通过使用IPv4数据报建立


    因此,如果一个IPv6的TCP客户指定一个IPv4映射的IPv6地址以调用connect,或者一个IPv6的UDP客户指定一个IPv4映射的IPv6地址以调用sendto,那么内核检测到这个映射地址后改为发送一个IPv4数据报而不是IPv6数据报

最后这里做一个总结:

IPv4 和 IPv6的互操作性