IPv6名稱到地址的轉換函式getaddrinfo()詳解

來源:互聯網
上載者:User

   轉自 http://desktop.chinaitlab.com/VC/27753.html

     IPv4中使用gethostbyname()函數完成主機名稱到位址解析,但是該API不允許調用者指定所需地址類型的任何資訊,返回的結構只包含了用於儲存IPv4地址的空間。為瞭解決該問題,IPv6中引入了getaddrinfo()的新API,它是協議無關的,既可用於IPv4也可用於IPv6。調用該函數會獲得一個addrinfo結構的列表,調用的傳回值是addrinfo的結構(列表)指標。
  
  本文結合在WinowsXP和Windows2003 Server上使用該函數的經驗,對getaddrinfo函數和addrinfo資料結構進行介紹,並對其參數的設定加以討論,主要包括nodename和servname的取值對傳回值的影響,hints成員變數的設定對傳回值的影響等。
  
  可能有不完全或不準確的地方,歡迎大家討論並指出。
  
  1.getaddrinfo函數原型
  

 

  Getaddrinfo提供獨立於協議的名稱解析。
  
  函數的前兩個參數分別是節點名和服務名。節點名可以是主機名稱,也可以是地址串(IPv4的點分十進位數表示或IPv6的十六進位數字串)。服務名可以是十進位的連接埠號碼,也可以是已定義的服務名稱,如ftp、http等。注意:其中節點名和服務名都是可選項,即節點名或服務名可以為NULL,此時調用的結果將取預設設定,後面將詳細討論。
  
  函數的第三個參數hints是addrinfo結構的指標,由調用者填寫關於它所想返回的資訊類型的線索。函數的傳回值是一個指向addrinfo結構的鏈表指標res。
  
  2.addrinfo結構
  

 

  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不作改動。

      (另在MSDN 中對 addrinfo 結構的解釋裡有關於ai_protocol 的註解:Protocol, such as IPPROTO_TCP or IPPROTO_UDP. For protocols other than IPv4 and IPv6, set ai_protocol to zero.)
  
  其中ai_flags、ai_family、ai_socktype說明如下:
  

 

  對於ai_flags值的說明:
  

 

  如上表所示,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成員中,應該包含一個以Null 字元結尾的字串,字串的內容是節點名的正規名。
  
  (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,否則庫函數和標頭檔可能都會有問題。

 

           

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.