支持IPV6的WINDOWS套接字变化

  • 格式:docx
  • 大小:89.42 KB
  • 文档页数:8

支持IPV6的WINDOWS套接字变化

发布: 2008-11-17 18:29 | 作者: admin | 来源: IPv6之家

1、增加的常量

IPV6的地址族名和协议族名常为:AF_INET6 PF_INET6

2、地址数据结构

struct in6_addr {

uint8_t s6_addr[16]; /* IPv6 address */

};

sockadd_in6用于包含一个IPV6地址

struct sockaddr_in6 {

short sin6_family; /* AF_INET6 */

u_short sin6_port; /* Transport level port

number */

u_long sin6_flowinfo; /* IPv6 flow

information */

struct in_addr6 sin6_addr; /* IPv6 address */

};

除了族、端口和地址信息,此结构中还包含sin6_flowinfo和sin6_scope_id数据成员

。在数据成员sin6_flowinfo中将包含IPV6报头中的通信流类别字段和流标签字段。在XP和

SERVER2003系统中不支持sin6_flowinfo数据成员。在数据成员sin6_scope_id中包含了范

围ID,它用于标识一系列的接口,这些接口与地址字段中的地址相对应

由于IPV4中sockaddr和IPV6中sockaddr_in6具有不同的长度,因此,不能使用struct

sockaddr来分配存储空间,然后将其强制转换为一个sockaddr_in6指针。如果需要为soc

kaddr_in6结构静态分配存储空间,则应该使用structsockaddr_storage,例如:

structsockaddr_storagenewaddr;

......

msgsock=accept(listen_socket,(structsockaddr

*)&newaddr,&newaddrlen);

3、通配地址

为了在具体的实现方案中为使用IPV4的连接或数据报选择一个源地址,在bind()函数

调用中将常量INADDR_ANY用作地址。

IPV6地址类型(in6_addr)是一个结构变量,不能用常量为结构变量赋值,但常量可以

用于初始化这个结构,全球变量in6addr_any可以在赋值中使用,如

sin6.sin6_addr=in6addr_any;

或者常量IN6ADDR_ANY_INIT也可用于初始化地址结构(只在声明的时候),如

struct in6_addr anyaddr=IN6ADDR_ANY_INIT;

在IPV4中的connect(),send()和sendmsg()函数调用中,使用常量INADDR_LOOPBACK来

和本地节点中的服务进行通信。对于IPV6的回环,全局变量(in6addr_loopback)在赋值中

使用,常量(IN6ADDR_LOOPBACK_INIT)用于在声明时的初始化。注意,IPV4的INADDR_XXX常

量以主机字节顺序定义,而IPV6的以网络字节顺序定义

4、核心套接字函数

在核心套接字函数中所进行的地址传递实际上是传递一个不透明的地址指针和长度,

因此,IPV6的核心套接字函数不需要对原来的进行改变。我们只需要简单地提供适当的IP

V6地址结构和族常量。接受地址参数的套接字函数有:

bind()

connect()

sendmsg()

sendto()

返回地址的套接字函数有:

accept()

recvfrom()

recvmsg()

getpeername()

getsockname()

5、名称到地址的转换

在IPV4中,应用程序使用gethostbyname()函数来将主机名解析为一个或多个IP地址, 但它不允许调用者指定所需地址类型的任何信息,因此IPV6中引入一个名字getaddrinfo(

)的新API,此API与协议无关,此调用的返回值是addrinfo的结构指针,以后可用它来打开

和使用套接字,getaddrinfo()原型如下:

intgetaddrinfo(

IN const char FAR *nodename,

IN const char FAR *servname,

IN conststructaddrinfo FAR *hints,

OUT structadrinfo FAR *FAR *res

);

structaddrinfo {

int ai_flags; /* AI_PASSIVE, AI_CANONNAME,

AI_NUMERICHOST */

int ai_family; /* PF_xxx */

int ai_socktype; /* SOCK_xxx */

int ai_protocol; /* 0 or IPPROTO_xxx for IPv4 and

IPv6 */

size_t ai_addrlen; /* length of ai_addr */

char *ai_canonname; /* canonical name for

nodename */

structsockaddr *ai_addr; /* binary address */

structaddrinfo *ai_next; /* next structure in linked list

*/

};

6、地址到名称的转换 反向查找可以通过使用另一个新的套接字函数getnameinfo()来进行,为使用此API,

调用者需要提供一个套接字地址结构。getnameinfo()原型如下:

intgetnameinfo(

IN conststructsockaddr FAR *sa,

IN socklen_tsalen,

OUT char FAR *host,

IN size_thostlen,

OUT char FAR *serv,

IN size_tservlen,

IN int flags

);

我们在编程时可以这样使用getaddrinfo()函数:

......

if (getaddrinfo(service_name,port,NULL,&ai)!=0)

{

/*error handling */

}

conn_socket=socket(ai->ai_family,ai->ai_socktype,ai->ai_protocol);

if(conn_socket<0)

{

/*eror handling*/

}

if(connect(conn_socket,ai->ai_addr,ai->ai_addrlen)==SOCKET_ERROR)

{ /*error handling*/

}

freeaddrinfo(ai);

7、地址转换函数

IPV4中使用inet_addr()和inet_ntoa()函数在IPV4地址的二进制格式和文本格式之间

进行转换,IETF也定了相似的函数inet_pton()和inet_ntop(),这两个函数是与协议无关

的,但XP和SERVER2003不支持这两个函数,而用getaddrinfo()和getnameinfo()来代替

8、套接字选项

在IPV6专用的套接字选项中,定义了一个新的套接字选项级别——IPPROTO_IPV6。新

的套接字选项如下:

IPV6_MULTICAST_IF:将自内向外的多播通信流所使用的默认接口设置为由参数所指定的索

引所表示的接口(0表示由系统选择接口)

IPV6_MULTICAST_HOPS:根据参数来设置自内向外的多播数据包的跳限制。有效值在-1~255

之间,其中-1表示使用系统的默认值

IPV6_MULTICAST_LOOP:用于控制目标为一个多播组的自内向外的多播数据包是否被环回。

对于多揪播通信流的接收,IPV6定义了新的选项来加入或离开一个多播组。这些选项 使用ipv6_mreq结构作为参数。

struct ipv6_mreq{

struct in6_addr ipv6mr_multiaddr;

unsignedint ipv6mr_interface;

};

新的多播套接字选项有:

IPV6_JOIN_GROUP:用于加入指定接口上的指定多播组(0表示由系统来选择接口)

IPV6_LEAVE_GROUP:用于离开指定接口上的指定多播组。

另外,还有一个套接字选IPV6_UNICAST_HOPS来控制自内向外的单播数据包的跳限制。

9、新的宏

为支持IPV6而新加入到WINDOWS套接字中的还有以下的宏集合,这些宏用于测试地址,

并确定它们是否为特殊的IPV6地址:

IN6_IS_ADDR_UNSPECIFIED

IN6_IS_ADDR_LOOPBACK

IN6_IS_ADDR_MULTICAST

IN6_IS_ADDR_LINKLOCAL

IN6_IS_ADDR_SITELOCAL

IN6_IS_ADDR_V4MAPPED

IN6_IS_ADDR_V4COMPAT

IN6_IS_ADDR_MC_NODELOCAL

IN6_IS_ADDR_MC_LINKLOCAL

IN6_IS_ADDR_MC_SITELOCAL

IN6_IS_ADDR_MC_ORGLOCAL