初識IPv6(四)

 
           第4 IPv6應用
 
       IPv6程序相對於IPv4改動並不大。其中主要的改動就是地址結構與地址解析函數。在RFC中詳細說明了socket api 爲適應IPv6所做的改動。而且windows平臺與Linux平臺在實現上也幾乎是一樣的。只不過頭文件與支持程度等有所不同罷了(具體請參見RFC 2553與RFC 2292)。如讀者有興趣的話可以找RFC來看看,在這裏就不再詳細說明,只講最簡單的原理與例子,同時例出各主要socket api,如何使用,可以參考MSDN或是Linux中的MAN。
        
1 增加的常量 IPV6的地址族名和協議族名常爲:AF_INET6  PF_INET6
地址表示
  IPv4使用32bits的地址表示,並有sockaddr_inin_addr等結構應用於API中,而IPv6 使用128 bits 地址,也定義了本身的地址結構sockaddr_in6in6_addr

  //ipv4 addr
struct sockaddr_in
{
u_char sin_len;
u_char sin_family;
u_short sin_port;
struct in_addr sin_addr;
char sin_zero[8];
};
struct in_addr
{
u_int32_t s_addr;
}
//ipv6 addr
 
struct sockaddr_in6
 {
u_char sin6_len;
u_char sin6_family;
u_int16_t sin6_port;
u_int32_t sin6_flowinfo;
struct in6_addr sin6_addr;
u_int32_t sin6_scope_id;
}
struct in6_addr
{
u_int8_t __u6_addr8[16];
}
 
除了族、端口和地址信息,此結構中還包含sin6_flowinfosin6_scope_id數據成員。在數據成員sin6_flowinfo中將包含IPV6報頭中的通信流類別字段和流標籤字段。在XP SERVER2003系統中不支持sin6_flowinfo數據成員。在數據成員sin6_scope_id中包含了範圍ID,它用於標識一系列的接口,這些接口與地址字段中的地址相對應
 
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的核心套接字函數不需要對原來的進行改變。我們只需要簡單地提供適當的IPV6地址結構和族常量。
接受地址參數的套接字函數有:
bind()
connect()
send()
sendto()
返回地址的套接字函數有:
accept()
recvfrom()
recv()
getpeername()
getsockname()
 

6、不受支持的API     XP和SERVER2003系列的IPV6協議不支持的API包括:
ninet_ntoa(),
ninet_addr(),
nhtonl(),
ngethostbyname(),
ngethostbyaddr(),
n
7、微軟提供了一個代碼升級檢測工具Checkv4.exe,在最新的SDK中,首先把SDK加入環境變量中,然後在命令行模式下切換到當前代碼所在的位子,輸入:
checkv4 "要檢測的代碼文件名"
就會顯示那些需要改變的代碼的地方.

 
有一系列的名稱/接口索引轉換不被支持,但可能以後支持。
更多信息請參考:RFC2553,RFC2292
5、名稱/地址的轉換     在IPV4中,應用程序使用gethostbyname()函數來將主機名解析爲一個或多個IP地址, 但它不允許調用者指定所需地址類型的任何信息,因此IPV6中引入一個名字getaddrinfo( )的新API,此API與協議無關,此調用的返回值是addrinfo的結構指針,以後可用它來打開 和使用套接字,getaddrinfo()原型如下:

int getaddrinfo(
    IN const char FAR *nodename,
    IN const char FAR *servname,
    IN const struct addrinfo FAR *hints,
    OUT struct addrinfo
 FAR *FAR *res
    );

struct addrinfo {
    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 */
    struct sockaddr  *ai_addr; /* binary address */
    struct addrinfo  *ai_next; /* next structure in linked list */
  };

 
反向查找可以通過使用另一個新的套接字函數getnameinfo()來進行,爲使用此API調用者需要提供一個套接字地址結構。getnameinfo()原型如下:

int 
getnameinfo(
    IN const struct sockaddr FAR 
*sa,
    IN socklen_t 
salen,
    OUT char FAR 
*host,
    IN size_t 
hostlen,
    OUT char FAR 
*serv,
    IN size_t 
servlen,
    IN int 
flags
    );
 
n
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章