生活随笔
收集整理的這篇文章主要介紹了
IPv6名称到地址的转换函数getaddrinfo()详解
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
? IPv4 中使用 gethostbyname() 函數完成主機名到地址解析,但是該 API 不允許調用者指定所需地址類型的任何信息,返回的結構只包含了用于存儲 IPv4 地址的空間。為了解決該問題, IPv6 中引入了 getaddrinfo() 的新 API ,它是協議無關的,既可用于 IPv4 也可用于 IPv6 。調用該函數會獲得一個 addrinfo 結構的列表,調用的返回值是 addrinfo 的結構(列表)指針。 ?????? 本文結合在 WinowsXP 和 Windows2003 Server 上使用該函數的經驗,對 getaddrinfo 函數和 addrinfo 數據結構進行介紹,并對其參數的設置加以討論,主要包括 nodename 和 servname 的取值對返回值的影響, hints 成員變量的設置對返回值的影響等。 可能有不完全或不準確的地方,歡迎大家討論并指出。 1.getaddrinfo函數原型 函數 參數說明 int getaddrinfo( const char* nodename const char* servname, const struct addrinfo* hints,// struct addrinfo** res ); nodename: 節點名可以是主機名,也可以是數字地址。( IPV4 的 10 進點分,或是 IPV6 的 16 進制) servname: 包含十進制數的端口號或服務名如( ftp,http ) hints: 是一個空指針或指向一個 addrinfo 結構的指針,由調用者填寫關于它所想返回的信息類型的線索。 res: 存放返回 addrinfo 結構鏈表的指針
Getaddrinfo 提供獨立于協議的名稱解析。 函數的前兩個參數分別是節點名和服務名。節點名可以是主機名,也可以是地址串 (IPv4 的點分十進制數表示或 IPv6 的十六進制數字串 ) 。服務名可以是十進制的端口號,也可以是已定義的服務名稱,如 ftp 、 http 等。注意:其中節點名和服務名都是可選項,即節點名或服務名可以為 NULL ,此時調用的結果將取缺省設置,后面將詳細討論。 函數的第三個參數 hints 是 addrinfo 結構的指針,由調用者填寫關于它所想返回的信息類型的線索。函數的返回值是一個指向 addrinfo 結構的鏈表指針 res 。 2.addrinfo結構 結構 固定的參數 typedef struct addrinfo {? int ai_flags;? int ai_family;? int ai_socktype;? int ai_protocol;? size_t ai_addrlen;? char* ai_canonname;? struct sockaddr* ai_addr;? struct addrinfo* ai_next; } ai_addrlen must be zero or a null pointer ai_canonname must be zero or a null pointer ai_addr must be zero or a null pointer ai_next must be zero or a null pointer 可以改動的參數 ai_flags:AI_PASSIVE,AI_CANONNAME,AI_NUMERICHOST ai_family: AF_INET,AF_INET6 ai_socktype: SOCK_STREAM,SOCK_DGRAM ai_protocol: IPPROTO_IP, IPPROTO_IPV4, IPPROTO_IPV6 etc.
3 參數說明 在 getaddrinfo 函數之前通常需要對以下 6 個參數進行以下設置: nodename 、 servname 、 hints 的 ai_flags 、 ai_family 、 ai_socktype 、 ai_protocol 在 6 項參數中,對函數影響最大的是 nodename , sername 和 hints.ai_flag 而 ai_family 只是有地址為 v4 地址或 v6 地址的區別。而 ai_protocol 一般是為 0 不作改動。 其中 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 當此標志置位時,此標志表示調用中的節點名必須是一個數字地址字符串。 4.實際使用的幾種常用設置 一般情況下, 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 。 5.幾句廢話 在 Windows 環境調試 IPv6 的程序個人感覺還是使用 WinXP ( SP2 )和 Win2003 基本上沒有太大的區別,使用 Win2003 更規范一些。 用 VC 編寫和調試 IPv6 的程序一定要安裝 Windows 較新的 SDK ,我安裝的是 MS_Platform_SDK_Feb_2003 ,否則庫函數和頭文件可能都會有問題。 ? [ 參考 ] [1]MSDN Library – January 2 004 ms-help://MS.MSDNQTR.2004JAN.1033/winsock/winsock/getaddrinfo_2.htm ms-help://MS.MSDNQTR.2004JAN.1033/winsock/winsock/addrinfo_2.htm [2] 《理解IPv6》("Understanding IPv6”),清華大學出版社 以上測試結果恐有不完善和錯誤的地方,歡迎大家指正,本人聯系方式:wjb@nlsde.buaa.edu.cn 王劍白
總結
以上是生活随笔 為你收集整理的IPv6名称到地址的转换函数getaddrinfo()详解 的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔 網站內容還不錯,歡迎將生活随笔 推薦給好友。