network program in ipv4 and ipv6 using getaddrinfo()

其中ai_flags、ai_family、ai_socktype說明如下:

參數     取值       值 說明
ai_family  AF_INET     2  IPv4
       AF_INET6     23 IPv6
       AF_UNSPEC    0  協議無關
ai_protocol IPPROTO_IP    0  IP協議
       IPPROTO_IPV4   4  IPv4
       IPPROTO_IPV6   41 IPv6
       IPPROTO_UDP   17 UDP
       IPPROTO_TCP   6  TCP
ai_socktype SOCK_STREAM   1  流
       SOCK_DGRAM    2  數據報
ai_flags   AI_PASSIVE    1  被動的,用於bind,通常用於server socket
       AI_CANONNAME   2   
       AI_NUMERICHOST  4  地址爲數字串

對於ai_flags值的說明:

AI_NUMERICHOST AI_CANONNAME AI_PASSIVE
0/1      0/1     0/1

如上表所示,ai_flagsde值範圍爲0~7,取決於程序如何設置3個標誌位,比如設置ai_flags爲 “AI_PASSIVE|AI_CANONNAME”,ai_flags值就爲3。三個參數的含義分別爲:

(1)AI_PASSIVE當此標誌置位時,表示調用者將在bind()函數調用中使用返回的地址結構。當此標誌不置位時,表示將在connect()函數調用中使用。
當節點名位NULL,且此標誌置位,則返回的地址將是通配地址。
如果節點名NULL,且此標誌不置位,則返回的地址將是迴環地址。

(2)AI_CANNONAME當此標誌置位時,在函數所返回的第一個addrinfo結構中的ai_cannoname成員中,應該包含一個以空字符結尾的字符串,字符串的內容是節點名的正規名。

(3)AI_NUMERICHOST當此標誌置位時,此標誌表示調用中的節點名必須是一個數字地址字符串。

實際使用的幾種常用設置
一般情況下,client/server編程中,server端調用bind(如果面向連接的還需要listen),client則不用掉bind函數,解析地址後直接connect(面向連接)或直接發送數據(無連接)。因此,比較常見的情況有

(1) 通常服務器端在調用getaddrinfo之前,ai_flags設置AI_PASSIVE,用於bind;主機名nodename通常會設置爲NULL,返回通配地址[::]。
(2) 客戶端調用getaddrinfo時,ai_flags一般不設置AI_PASSIVE,但是主機名nodename和服務名servname(更願意稱之爲端口)則應該不爲空。
(3) 當然,即使不設置AI_PASSIVE,取出的地址也並非不可以被bind,很多程序中ai_flags直接設置爲0,即3個標誌位都不設置,這種情況下只要hostname和servname設置的沒有問題就可以正確bind。

上述情況只是簡單的client/server中的使用,但實際在使用getaddrinfo和參考國外開源代碼的時候,曾遇到一些將servname(即端口)設爲NULL的情況

(當然,此時nodename必不爲NULL,否則調用getaddrinfo會報錯)。以下分情況進行了測試:

(1) 如果nodename是字符串型的IPv6地址,bind的時候會分配臨時端口;
(2) 如果nodename是本機名,servname爲NULL,則根據操作系統的不同略有不同,本文僅在WinXP和Win2003上作了測試。

a) WinXP系統(SP2)返回loopback地址[::1]
b)Win2003則將本機的所有IPv6地址列表加以返回。因爲通常一臺IPv6主機都有可能不止一個IPv6地址,比如fe80::1(本機loopback地址)、fe80::***的Link-Local地址、3ffe:***的全局地址等等。這種情況下調用getaddrinfo會將這些地址全部返回,調用者應該注意如何使用這些地址。另外要注意的是,對於fe80::的地址在綁定的時候必須標明接口地址,即使用fe80::20d:60ff:fe78:51c2%4或fe80::1%1這樣的地址格式,通過getaddrinfo直接取出fe80地址好像無法直接bind。

在Windows環境調試IPv6的程序個人感覺還是使用WinXP(SP2)和Win2003基本上沒有太大的區別,使用Win2003更規範一些。

用VC編寫和調試IPv6的程序一定要安裝Windows較新的SDK,我安裝的是MS_Platform_SDK_Feb_2003,否則庫函數和頭文件可能都會有問題。

發佈了40 篇原創文章 · 獲贊 0 · 訪問量 5萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章