基于IPv4/IPv6双协议栈的通信模块及实现作者:解慧娟,林南晖
来源:《软件导刊》2011年第11期
摘要:介绍了IPv6下的套接字地址结构及Socket API函数,通过在IPv4/IPv6双协议栈服务器端创建一个IPv6套接字,并调用IPv6下协议无关的Socket API函数,实现了一个基于TCP 的客户/服务器通信模块。实验证明,该通信模块能同时支持IPv4与IPv6。
关键词:双协议栈;Pv6套接字;Socket API 函数;客户/服务器通信模块
中图分类号:TP311.52 文献标识码:A 文章编号:1672-7800(2011)011-0110-
1 Socket编程基础
1.1 socket接口分析
socket是套接字的功能实体,在socket编程中,首先要用socket( )创建一个套接字,通常由3个参数唯一确定:①address family,地址簇,PF_INET代表IPv4地址簇,PF_INET6代表IPv6地址簇;②type,连接类型,SOCK_STREAM即流式套接口,基于TCP,定义了一种可靠的,面向连接的服务,流式套接字通信流程如图1所示,SOCK_DGRAM即数据报套接口,基于UDP,定义了一种无连接的服务;③protocol,协议类型,通常设置为0,可使系统选择默认的由地址簇和连接类型所确定的协议。
1.2 IPv6套接字地址数据结构
IPv4的IP地址长32位,而IPv6地址长128位,因此在IPv6套接字中,地址数据结构必须做出改变来适应IPv6地址长度的改变。在中分别定义了一种新的地址簇---AF_INET6和新的协议簇---PF_INET6,前者将原来的sockaddr_in 数据结构与新的sockaddr_in6 数据结构同区分开,后者将在创建socket 时使用,表明创建的是一个IPV6套接字。
IPv6套接字地址结构以sockaddr_in6命名,它在头文件中的定义如下:
unit8_t s6_addr[16]; /*128位的IPv6地址,网络字节顺序存储
unit8_t sin6_len; /*结构体的长度
sa_family_t sin6_family; /*套接字类型为
in_port_t sin6_port; /*传输层端口号
struct in6_addr sin6_addr; /*128位的IPv6地址,网络字节顺序存储
unit32_t sin6_flowinfo; /*IPv6优先级&流量标记
1.3 IPv6的Socket API函数
IPv6的Socket API函数中的一部分沿用了IPv4的Socket API函数,为了满足对IPv6地址的不同操作,库函数定义了新的函数来实现相应的功能。
(1)域名与地址的转换函数,查找主机名的基本函数是gethostbyname( )或gethostbyname2( ),虽然能查询IPv4或IPv6地址,但对许多应用程序来说是不够的,而且这些函数在线程中不是安全的。getipnodebyname()作为新增的函数实现对DNS 执行一个对A 记录的查询或AAAA 记录的查询,它返回的是IPv4 或IPv6 地址,并保证了线程的安全。getipnodebyname()的行为正好相反,它根据一个二进制的IP地址查找相应于此地值得主机名。
(2)地址转换函数,适用于IPv4地址的是inet_aton( )和inet_ntoa( )函数,新增的
inet_pton( )和inet_ntop( )函数对IPv4和IPv6地址都能进行处理,其中p代表presentation,指ASCII字符串,n代表numeric,指套接字结构中的二进制。在调用inet_pton( )和inet_ntop( )函数时,需要调用者指明地址是in_addr还是in_addr6结构,因此必须编写额外的代码段。
(3)协议无关的转换函数,在域名与地址之间进行转换且与地址簇无关的新增转换函数主要有两个:getaddrinfo( )和getnameinfo( ),它由一个指针来引用套接口地址,隐藏了名字和地址转换的大量细节,实现了代码协议无关性,因此可以代替inet_pton( )、inet_ntop( )、gethostbyname( )等函数的功能。
2 双协议栈下socket通信模块的实现原理
双协议栈技术即在设备上同时启用IPv4和IPv6协议栈,如果一台主机同时支持IPv4和IPv6这两种协议,则该主机被称为双协议栈主机,既能处理IPv4连接也能处理IPv6连接。
在客户/服务器模式下,双协议栈主机上运行的服务器端既能接受IPv4客户端的连接也能
接受IPv6客户端的连接。其工作流程如下:
当IPv6套接字收到IPv6数据包时,不需要做任何特殊处理,服务器和客户端交互的是IPv6数据包。当IPv6套接字收到IPv4数据包时,系统会在accept( )调用返回地址时将对应的
IPv4地址映射的IPv6地址返回。服务器和客户端交换的是IPv4数据包。
基于对IPv6 socket编程及双协议栈工作机制的分析,本文在双协议栈服务器端建立一个IPv6套接字,并在visual studio 2010环境使用C++开发了一个基于TCP的客户/服务器通信模
块,该模块能同时支持IPv4和IPv6。
3 双协议栈下socket通信模块的具体实现
分别在服务器端和客户端开发了两个模块server与client,通过这两个模块,可以在客户端把服务器端的IP地址作参数,和服务器端进行信息交换,现在把server和client中的部分重要程序段加以分析。
3.1 服务器端模块的程序设计
服务器端模块运行在Linux下,IPv4地址为192.168.40.129,IPv6地址为
fe80::20c:29ff:feeb:bce7/64,监听端口号为8796。
服务器端模块server编程步骤及关键代码如下:
(1)定义函数parsedata( ),该函数的作用是接受客户端数据并对它做出响应。
(2)调用socket( )创建一个IPv6套接字。
IPPROTO_TCP);
in6_addr add