前言

因为互联网终端不断添加。IPv4 地址长度(32位)已不可以满足要求。所以出现了 IPv6地址(128位)。可是现有应用程序大部分还是採用 IPv4 地址形式,所以必须解决 IPv4 与 IPv6 之间的相互操作,使现有基于 IPv4 的应用程序可以与基于 IPv6 的应用程序相互通信。那么我们怎么实现 IPv4 client与 IPv6 server、IPv6 client与 IPv4 server之间的通信。

IPv4 client与 IPv6 server

如果我们主机是执行双栈,即存在 IPv4 协议栈和 IPv6 协议栈,双栈主机上的 IPv6 server既能处理 IPv4 client。也能处理 IPv6 client,由于 IPv4 能够映射成 IPv6 地址。下图是 IPv4 client与 IPv6 server之间的通信过程:

IPv6 server程序创建的套接字绑定到 IPv6 通配地址和 TCP port号 9999。

如果client和server主机都处于同一个以太网,当左側两个client都发送 SYN 报文段请求与server建立连接时,IPv4 client主机在一个 IPv4 数据报中载送 SYN,IPv6 client主机在一个 IPv6 数据报中载送 SYN。

在以太网线上包括以太网首部、IP 首部、TCP 首部以及 TCP 数据,依据以太网首部中包括的类型字段区分 IP 类型是为 IPv4 还是 IPv6,因此 IP 首部中的目的 IP
地址格式依据以太网类型字段分为 IPv4 地址和 IPv6 地址。两者的 TCP 首部是一样的。TCP 首部中包括目的port号(即 IPv6 server的port号 9999)。

server的接收数据链路通过查看以太网类型字段把每帧传递给相应的 IP 模块。IPv4 模块结合其上的 TCP 模块检測到 IPv4 数据报的目的port相应的是一个 IPv6 套接字,于是把该数据报 IPv4 首部中的源 IPv4 地址转换成一个等价的 IPv4 映射的 IPv6 地址。

当 accept 系统调用把这个已经接受的 IPv4 client连接返回给server进程时,这个映射后的地址将作为客户的 IPv6 地址返回给server的 IPv6 套接字(也就是说server根本不知道自己是在跟 IPv4 client通信。client也不知道自己和
IPv6 的server通信)。该连接上其余的数据报都是 IPv4 数据报。对于 IPv6 client,当 accept 系统调用把接受的 IPv6 client连接返回给server进程时。该客户的 IPv6 地址就是原来 IPv6 首部中的源地址,不须要进行映射。该连接上其余的数据报都是 IPv6 数据报。

IPv4 的 TCP client与 IPv6 的 TCP server之间通信的过程例如以下:

  1. 首先启动 IPv6 server,创建一个 IPv6 的监听套接字,而且该server把通配地址和port号 9999 绑定到该套接字上;
  2. IPv4 client调用 gethostbyname 函数找到server主机的一个 A 记录。server同一时候包括 A 记录和 AAAA 记录,即同一时候支持 IPv4 和 IPv6,对于 IPv4 client来说仅仅须要 A 记录就可以;
  3. IPv4 client调用 connect 函数向server发出连接请求,即client主机向server主机发送一个 IPv4 的 SYN 数据报(该 IPv4 的 SYN 中的目的地是 IPv6 套接字);
  4. server主机接收到来自client的 IPv4 的 SYN 数据报后,设置一个标志指示本连接应使用 IPv4 映射的 IPv6 地址。并响应一个 IPv4 的SYN 和 ACK 数据报。

    当该链接建立后。由 accept 函数把这个 IPv4 映射的 IPv6 地址返回给server;

  5. 当server主机往这个 IPv4 映射的 IPv6 地址发送 TCP 报文段时,其 IP 栈产生目的地址为所映射 IPv4 地址的 IPv4 载送数据报。即client和server之间全部通信都使用 IPv4 的载送数据报。

IPv6 client与 IPv4 server

IPv6 的 TCP client与 IPv4 的 TCP server之间通信的过程例如以下:

  1. 首先启动 IPv4 server,创建一个 IPv4 的监听套接字。
  2. IPv6 client调用 getaddrinfo 函数查找 IPv6 地址。
  3. IPv6 client在作为函数參数的 IPv6 套接字地址结构中设置这个 IPv4 映射的 IPv6 地址后调用 connect 函数向server发出连接请求。内核检測到这个映射地址后,自己主动向server主机发送一个 IPv4 的 SYN 数据报;
  4. server主机接收到来自client的 IPv4 的 SYN 数据报后。响应一个 IPv4 的SYN 和 ACK 数据报。

    连接通过使用 IPv4 数据报建立。

总结

双栈主机上的 IPv6 server既能服务于 IPv4 客户,又能服务于 IPv6 客户。

IPv4 客户发送给这样的server的仍然是 IPv4 数据报。只是server的协议栈会把客户主机的地址转换成一个 IPv4 映射的 IPv6 地址。类似地。双栈主机上的 IPv6 客户可以与 IPv4 server通信,客户的解析器会把server主机全部的 A 记录作为 IPv4 映射的 IPv6 地址返回给客户,而客户指定这些地址之中的一个调用 connect 将会使双栈发送一个 IPv4 的 SYN 数据报。为了使套接字编程具有可移植性。在编程实现过程中,尽量避免使用
gethostbyname 和 gethostbyaddr 函数,而应该使用 getaddrinfo 和 getnameinfo 函数。

參考资料:

《Unix 网络编程》

《网络编程》IPv4 与 IPv6 相互操作的更多相关文章

  1. [转载]Linux网络编程IPv4和IPv6的inet_addr、inet_aton、inet_pton等函数小结

    转载:http://blog.csdn.net/ithomer/article/details/6100734 知识背景: 210.25.132.181属于IP地址的ASCII表示法,也就是字符串形式 ...

  2. Linux网络编程IPv4和IPv6的inet_addr、inet_aton、inet_pton等函数小结

    知识背景: 210.25.132.181属于IP地址的ASCII表示法,也就是字符串形式.英语叫做IPv4 numbers-and-dots notation. 如果把210.25.132.181转换 ...

  3. Linux网络编程IPv4和IPv6的inet_addr、inet_aton、inet_pton等函数小结(转)

    原文:http://blog.csdn.net/ithomer/article/details/6100734 知识背景: 210.25.132.181属于IP地址的ASCII表示法,也就是字符串形式 ...

  4. 网络类型IPv4和IPv6什么意思?区别?

    在windows 7以上系统中,在设置本地IP地址的时候经常会看到同事含有IPV4协议项与IPV6协议项,并不同于以往windows xp系统中仅有TCP/IP协议项,不少朋友都觉得比较奇怪,询问编辑 ...

  5. UNIX网络编程--IPV4 IPV6 ICMPV4 ICMPV6

    一.IPV4首部 IP层提东无连接不可靠的数据报递送服务.它会尽力把IP数据报递送到指定的目的地,然而并不保证他们一定到达,也不保证他们的到达顺序与发送顺序一致,还不保证每个IP数据报只到达一次.任何 ...

  6. Linux 网络编程(一)--Linux操作系统概述

    一.Linux的内核版本 Linux内核的编号采用如下编号形式: 主版本号.此版本号.主补丁号.次补丁号 例如:2.6.26.3 第一个数字”2”是主版本号,表示第2大版本. 第二个数字”6”是此版本 ...

  7. python之网络编程

    本地的进程间通信(IPC)有很多种方式,但可以总结为下面4类: 消息传递(管道.FIFO.消息队列) 同步(互斥量.条件变量.读写锁.文件和写记录锁.信号量) 共享内存(匿名的和具名的) 远程过程调用 ...

  8. Python开发【第八篇】:网络编程 Socket

    Socket socket通常也称作"套接字",用于描述IP地址和端口,是一个通信链的句柄,应用程序通常通过"套接字"向网络发出请求或者应答网络请求. sock ...

  9. python——网络编程

    Socket socket通常也称作"套接字",用于描述IP地址和端口,是一个通信链的句柄,应用程序通常通过"套接字"向网络发出请求或者应答网络请求. sock ...

随机推荐

  1. 【noip模拟赛5】水流

    描述 全球气候变暖,小镇A面临水灾.于是你必须买一些泵把水抽走.泵的抽水能力可以认为是无穷大,但你必须把泵放在合适的位置,从而能使所有的水能流到泵里.小镇可以认为是N * M的矩阵.矩阵里的每个单元格 ...

  2. 016 Spark中关于购物篮的设计,以及优化(两个点)

    一:介绍 1.购物篮的定义 2.适用场景 3.相关概念 4.步骤 5.编程实现 6.步骤 二:程序 1.程序 package com.ibeifeng.senior.mba.association i ...

  3. SparseArray源码解析

    转载自SparseArray源码解析 No1: Android官方推荐:当使用HashMap(K, V),如果K为整数类型时,使用SparseArray的效率更高. No2: HashMap是使用数组 ...

  4. web漏洞扫描工具AWVS使用

    AWVS AWVS简介:Acunetix Web Vulnerability Scanner(简称AWVS)是一款知名的网络漏洞扫描工具,它通过网络爬虫测试你的网站安全,检测流行安全漏洞,如交叉站点脚 ...

  5. BZOJ.3638.CF172 k-Maximum Subsequence Sum(模拟费用流 线段树)

    题目链接 各种zz错误..简直了 /* 19604kb 36292ms 题意:选$k$段不相交的区间,使其权值和最大. 朴素线段树:线段树上每个点维护O(k)个信息,区间合并时O(k^2),总O(mk ...

  6. Python3练习题系列(01)

    2018-06-13 题目: 根据用户回答做出相应的判断,完成一个“回答-判断”的小游戏 Python3知识点: if, else, elif 实例代码: print("You enter ...

  7. linux命令(及解压tar.gz文件)

    https://wenku.baidu.com/view/f5805017866fb84ae45c8df3.html 1.压缩命令: 命令格式:tar  -zcvf   压缩文件名.tar.gz   ...

  8. WordPress主题开发实例:利用侧边栏工具显示联系方式

    利用侧边栏显示联系方式是很方便的 一.先开启侧边栏工具,在functions.php加上 $args = array( 'name' => __( '分类侧边栏'), 'id' => 'c ...

  9. c++中string类对象和字符数组之间的相互转换

    string类在c++中是一个模板类,位于名字空间std中,注意这里不是string.h,string.h是C字符串头文件. 将string类型转换为字符数组char arr[10];string s ...

  10. 如何让FireFox/chrome新打开的标签页在后台打开,而不是立即跳转过去

    firefox: 地址栏输入about:config 找到下面三项,全部设为true browser.tabs.loadInBackground browser.tabs.loadDivertedIn ...