摘 要:在分析IPv4和IPv6编程接口基础上,给出了一组兼容IPv4与IPv6的Winsock网络编程规则, 并叙述IPv6在WindowsXP系统下的安装和配置过程, 最后给出了一个可同时应用于IPv4和IPv6的实现Daytime协议的程序,此程序今后可以方便地进行其他应用协议及软件的移植,以适应IPv6的快速发展。
关键词:IPv6;Winsock;TCP;API;Daytime协议;网络编程
中图分类号:TP393 文献标识码:A 文章编号:1004-373X(2009)04-105-03
Research of Winsock Network Programming Compatible with IPv4&IPv6;
GUO Jingying
(Institute of Information and Control Engineering,Xi′an University of Architecture and Technology,Xi′an,710055,China)
Abstract:This article analyses the differences between IPv4 APIs and IPv6 APIs.On this basis,a set of Winsock programming rules with the IP version-compatible are given.Then it introduces how to install and configure IPv6 in Windows XP OS.Finally it gives a program to achieve Daytime protocol with the IP version-compatible.This process can transplant other application agreements and softwares easily in future to accommodate the rapid development of IPv6.
Keywords:IPv6;Winsock;TCP;API;Daytime protocol;network programming
0 引 言
随着通信技术和网络技术的飞速发展,特别是近年来,IPv4协议面临着一些难以解决的问题,如地址短缺、缺乏服务质量控制QoS和安全性差等。为了应对这一挑战,IETF(Internet Engineer Task Force) 组织提出了为适应未来对于网络基础设施数量和质量需求而设计的下一代互联网协议IPv6。IPv6继承了IPv4的优点,并根据IPv4多年来运行的经验进行了大幅度的修改和功能扩充,其扩展性、路由、安全性、配置和可靠性都有明显改进。
1 IPv6相对于IPv4 WinSock的改变
1.1 IPv6中新增加的常量
为了支持IPv6,需要定义一个新的地址族名,以便正确地识别和解析IPv6的地址结构。同样,还需要定义一个新的协议簇名(与地址族名具有相同的值),这样就可以使用合适的协议创建一个套接字。新定义的IPv6地址簇名和协议簇名常量为: AF_ INET6和PF_ INET6。
1.2 IPV6中新增加的地址结构
IPv6的地址结构通过struct in6_addr和struct sockaddr_in6定义,结构定义分别如下:
struct in6_addr {
u_chars6_addr[16];//IPv6地址
};
struct sockaddr_in6
{
u_char sin6_len; //地址长度
u_char sin6_family; // IP地址族,必须为AF_INET6
u_short sin6_port;//端口号,和IPv4中意义相同
u_long sin6_flowinfo; //标记连接通信量
struct in6_addr sin6_addr;//128位的IPv6网络地址
u_long sin6_scope_id;//地址接口识别号
};
1.3 IPV6中新增加的域名解析函数
IPv6引入了名为getaddrinfo()和getnameinfo()的新的API。这两个API是与协议无关的,且既可用于IPv4,也可用于IPv6的名称解析。getaddrinfo()函数的返回值是addrinfo的结构指针。
addrinfo结构如下所示:
struct addrinfo {
int ai_flags;//地址信息标志
int ai_family; //地址簇,对于IPv6地址必须是AF_INET6
int ai_socktype; //sodket类型,字节流用SOCK-STREAM,数据报用SOCK-DGRAM
int ai_protocol;//TCP协议用IPPROTO-TCP,UDP协议用IPPROTO-UDP
size-t ai_addrlen; //ai-addr地址长度
char *ai_canonname;//规范名
struct sockaddr *ai_addr; //地址
struct addrinfo *ai_next;//指向下一个结构信息指针
};
getaddrinfo()函数原型如下:
getaddrinfo(
IN const char FAR *nodename, //主机名地址或者是IP地址
IN const char FAR *servname,//服务名或十进制端口号
IN const struct addrinfo FAR *hints,// 指向addrinfo结构的指针
Out struct addrinfo FAR *FAR *res
);
getaddrinfo()函数可以把主机名或服务名转换成一组socket地址。 hints相当于一个过滤器,只有符合hints结构的内容才会返回到res指针中。执行成功后,参数res以链表的形式返回解析出来的地址,可以将这些地址直接传递给bind(),connect(),sendto()等函数。
地址到名称的转换可以通过另一个新的套接字函数getnameinfo()进行。getnameinfo()函数的功能与getaddrinfo()函数相反,该函数接受已经初始化的套接字结构,并返回与地址及端口信息对应的主机和服务.
2 兼容IPv4与IPv6的WinSock网络编程规则
2.1 使用sockaddr_storage结构
sockaddr_storage结构是新的套接字结构,它与协议无关,并拥有充分的地址空间容纳IPv4或者IPv6地址信息,且可以很方便地转换成sockaddr_in结构和sockaddr_in6结构。同时,这个结构还具有针对64位对齐问题的填充项,使用这个结构可以很容易地写出与地址协议簇无关和跨平台的程序代码,因此编写兼容IPv4与IPv6的网络程序时要使用这个结构表示网络地址。
sockaddr_storage结构定义如下:
struct sockaddr_storage{
u_char ss_len;
u_char ss_family;
u_char padding[128-2];
};
2.2 使用新的名称解析函数getaddrinfo()和getnameinfo()
这两个函数是随IPv6引进的新的名称解析函数,与地址协议簇无关,隐藏了名字到地址转换和地址到名字转换的大量细节,既能够处理IPv6地址,也能处理IPv4地址。它们也替代性地实现了下列函数接口的功能:gethostbyname(),gethostbyaddr(),inet_ntoa(),inet_aton(),getservbyname(),getservbyport()。可以在简化程序的同时实现与地址协议簇无关的编程,还可以提高程序的可移植性。
3 IPv4与IPv6双协议试验平台的搭建
由于大部分用户的操作系统都是Windows XP,所以在此仅介绍Windows XP下IPv6的安装与配置。
Windows XP操作系统内置了IPv6协议栈,提供了一组命令行方式的IPv6检测配置工具。在XP下安装IPv6协议后,对原IPv4协议的使用不产生任何影响,整个网络上各终端设备能够在一个物理网络上共享IPv4和IPv6协议,并支持2种协议的数据传输,即:所谓的双栈(DualStack)共享。
安装IPv6协议和配置地址及默认网关的过程如下:
D:\>ipv6 install
Installing….
Succeeded.
D:\>netsh
netsh>interface ipv6 add address "本地连接" 2008::a:20
确定
netsh>interface ipv6 add route::/0 "本地连接" 2008::a:20 publish=yes
确定
netsh>quit
D:\>
在安装和配置完成后,可使用ping6和tracert6命令检测网络连通和路由状态。
4 VC环境下Daytime协议的实现
根据以上所述,下面开发一个可同时应用于IPv4和IPv6的实现Daytime协议的程序。该程序基于C/S结构,客户端使用TCP协议连接到服务器端,向服务器发送请求;服务器收到请求后,将当前的时间发回客户端。
4.1 服务器端程序设计
服务器端首先启动,通过调用socket()建立一个Socket,然后调用bind()将该Socket和本地网络地址联系在一起,再调用listen()使Socket做好侦听的准备,并规定请求队列的长度,之后就调用accept()接收连接。连接建立后,服务器端创建一个通信用的Socket, 把当前时间发回给客户端。最后,在数据传送结束后,调用close()关闭Socket。
服务器端设计过程如下:
(1) 创建服务器端套接字
memset (&hints;,0,sizeof (hints));
hints.ai_family = PF_UNSPEC; //兼容IPv4与IPv6协议
hints.ai_socktype = SOCK_STREAM; //指定用字节流
hints.ai_protocol = IPPROTO_TCP; //指定用TCP协议
hints.ai_flags = AI_NUMERICHOST; //IP用数字表示
rc = getaddrinfo (NULL,"5001",&hints;,&res;); //解析本机地址
s_send= socket (res->ai_family,res->ai_socktype,res->ai_protocol); //创建用于连接的Socket
(2) 绑定本机监听端口
rc=bind(s_send,res->ai_addr,res->ai_addrlen);
(3) 监听并接收连接
listen(s_send,5);//创建连接队列,开始监听
new_fd=accept(s_send,(struct sockaddr*)&sin;,&sin;_len);//接受一个连接
(4) 处理连接,发回一个当前时间给客户端
while (1) {
time(&now;);
pts = ctime(&now;);
send(new_fd,pts,strlen(pts),0);
closesocket(new_fd);
}
(5) 关闭套接字
close(s-send );
4.2 客户端程序设计
客户端创建一个Socket,并调用connect()和服务器建立连接。连接建立后,客户端等待服务器返回的当前时间。最后,待数据传送结束后,调用close()关闭Socket。
客户端设计过程如下。
(1)创建客户端套接字
memset (&hints;,0,sizeof (hints));
hints.ai_family = PF_UNSPEC; //兼容IPv4与IPv6协议
hints.ai_socktype=SOCK_STREAM;//指定用字节流
hints.ai_protocol = IPPROTO_TCP; //指定用TCP协议
hints.ai_flags = AI_NUMERICHOST; //IP用数字表示
rc = getaddrinfo (NULL,“5001”,&hints;,&res;); //解析本机地址
s_send= socket (res->ai_family,res->ai_socktype,res->ai_protocol); //创建用于连接的socket
(2) 连接服务器
connect(s_send,res->ai_addr,res->ai_addrlen);
(3) 接收当前时间
cc = recv(s_send,buf,LINELEN,0);
(4) 关闭套接字
close (s-send);
5 程序运行后的结果
当服务器运行后,可同时在IPv4和IPv6地址监听,客户端向服务器发送请求,服务器接到请求后,向客户端返回一个当前时间。此实验达到了预期效果。
服务器端运行结果如图1所示。
6 结 语
虽然IPv6网络已经开始实验性部署,但是IPv4网络向IPv6网络的过渡和互通仍有一定难度,IPv4和IPv6网络还需共存一段时间,因此开发能够同时支持IPv4和IPv6的网络应用程序会变得越来越重要。
在此编写了一个能够同时支持IPv4和IPv6协议的程序,此程序可以方便地进行今后其他应用协议及软件的移植,需在服务器端设计过程(4)及客户端设计过程(3)中根据其具体协议及软件进行相应改变。
参 考 文 献
[1]RFC2292.Advanced Sockets API for IPv6[S].1998.
[2]RFC3493.Basic Socket Interface Extensions for IPv6[S].2003.
[3]COMER.TCP/IP网络互连技术(卷3)[M].张卫,王能,译.北京:清华大学出版社,2000.
[4]Stevens W R.TCP/IP详解(卷3)[M].胡谷雨,译.北京:机械工业出版社,2000.
[5]马仝芬,付晓玲.IPv4与 IPv6兼容网络编程模式[J].北方工业大学学报,2005(3):25-29.
[6]刘利强,吴永英,王勇智.IPv6下Socket网络编程的研究与实现[J].计算机技术与发展,2006,16(6):201-203,206.
[7]朱坤华,朱国超.基于IPv6的网络编程实例剖析[J].移动计算,2006(2):257-259.
[8]袁德明.用IPv6编程接口实现有连接通信的方法[J].计算机时代,2007(9):23-24,27.
作者简介 郭静盈 女,1983年出生,河南漯河人,硕士。主要研究方向为基于IPv6的Winsock网络编程。