共用方式為


ADDRINFOEXW 結構 (ws2def.h)

GetAddrInfoEx 函式會使用 addrinfoex 結構來保存主機地址資訊。

語法

typedef struct addrinfoexW {
  int                ai_flags;
  int                ai_family;
  int                ai_socktype;
  int                ai_protocol;
  size_t             ai_addrlen;
  PWSTR              ai_canonname;
  struct sockaddr    *ai_addr;
  void               *ai_blob;
  size_t             ai_bloblen;
  LPGUID             ai_provider;
  struct addrinfoexW *ai_next;
} ADDRINFOEXW, *PADDRINFOEXW, *LPADDRINFOEXW;

成員

ai_flags

類型: int

旗標,指出 GetAddrInfoEx 函式中使用的選項。

ai_flags成員的支援值定義於 Winsock2.h include 檔案中,而且可以是下列選項的組合。

意義
AI_PASSIVE
0x01
套接字位址將用於對 bind 函式的呼叫。
AI_CANONNAME
0x02
標準名稱會在第一 個ai_canonname 成員中傳回。

設定 AI_CANONNAMEAI_FQDN 位時,會傳回 addrinfoex2 結構,而不是 addrinfoex 結構。

AI_NUMERICHOST
0x04
傳遞至 GetAddrInfoEx 函式的 nodename 參數必須是數值字串。
AI_ALL
0x0100
如果設定此位,則會針對具有 AI_V4MAPPED的 IPv6 位址和 IPv4 位址提出要求。

Windows Vista 和更新版本支援此選項。

AI_ADDRCONFIG
0x0400
只有在設定全域位址時 ,GetAddrInfoEx 才會解析。 IPv6 和 IPv4 回送位址不會被視為有效的全域位址。

只有 Windows Vista 和更新版本才支援此選項。

AI_V4MAPPED
0x0800
如果 IPv6 位址的 GetAddrInfoEx 要求失敗,則會針對 IPv4 位址提出名稱服務要求,而且這些位址會轉換成 IPv4 對應 IPv6 位址格式。

Windows Vista 和更新版本支援此選項。

AI_NON_AUTHORITATIVE
0x04000
地址資訊來自非授權結果。

當此選項在 GetAddrInfoExpHints 參數中設定時,NS_EMAIL命名空間提供者會同時傳回授權和非授權結果。 如果未設定此選項,則只會傳回授權結果。

GetAddrInfoEx 所傳回的 ppResults 參數中,此旗標會在 addrinfoex 結構的ai_flags成員中設定為非授權結果。

只有 windows Vista 和更新版本的 windows Vista 才支援此選項 ,NS_EMAIL 命名空間。

AI_SECURE
0x08000
地址信息來自安全通道。 如果設定 AI_SECURE 位, NS_EMAIL 命名空間提供者會傳回以增強安全性取得的結果,以將可能的詐騙降到最低。

當此選項在 GetAddrInfoExpHints 參數中設定時,NS_EMAIL命名空間提供者只會傳回以增強安全性取得的結果,以將可能的詐騙降到最低。

GetAddrInfoEx 所傳回的 ppResults 參數中,此旗標會設定在 addrinfoex 結構的ai_flags成員中,以增強安全性傳回的結果,以將可能的詐騙降到最低。

只有 windows Vista 和更新版本的 windows Vista 才支援此選項 ,NS_EMAIL 命名空間。

AI_RETURN_PREFERRED_NAMES
0x010000
地址資訊適用於具有特定命名空間之發行集的慣用名稱。

當此選項在 GetAddrInfoExpHints 參數中設定時,pName 參數中不應該提供任何名稱,而且NS_EMAIL命名空間提供者會傳回發行集的慣用名稱。

GetAddrInfoEx 所傳回的 ppResults 參數中,此旗標會在 addrinfoex 結構的ai_flags成員中設定,以取得針對發行集慣用名稱傳回的結果。

只有 windows Vista 和更新版本的 windows Vista 才支援此選項 ,NS_EMAIL 命名空間。

AI_FQDN
0x00020000
完整功能變數名稱會在第一個 ai_canonicalname 成員中傳回。

GetAddrInfoExpHints 參數中設定此選項,並在 pName 參數中指定單一標籤 (單一卷標) 的一般名稱時,最終會傳回名稱的完整功能變數名稱。

設定 AI_CANONNAMEAI_FQDN 位時,會傳回 addrinfoex2 結構,而不是 addrinfoex 結構。

Windows 7、Windows Server 2008 R2 和更新版本支援此選項。

AI_FILESERVER
0x00040000
命名空間提供者的提示,指出正在查詢的主機名正用於檔案共用案例中。 命名空間提供者可能會忽略此提示。

Windows 7、Windows Server 2008 R2 和更新版本支援此選項。

AI_DISABLE_IDN_ENCODING
0x00080000
GetAddrInfoEx 函式所呼叫的名稱解析函式中使用 Punycode 停用自動國際域名編碼。

Windows 8、Windows Server 2012 及更新版本支援此選項。

ai_family

類型: int

位址系列。 位址系列的可能值定義於 Winsock2.h include 檔案中。

在針對 Windows Vista 和更新版本發行的 Windows SDK 上,頭檔的組織已變更,而且位址系列的可能值定義在 Ws2def.h 頭檔中。 請注意, Ws2def.h 頭文件會自動包含在 Winsock2.h 中,不應該直接使用。

目前支援的值是 AF_INETAF_INET6,這是IPv4和IPv6的因特網位址系列格式。 如果已安裝位址系列的 Windows Sockets 服務提供者,則支援位址系列 (AF_NETBIOS 用於 NetBIOS 的其他選項,例如,如果已安裝位址系列的 Windows 套接字服務提供者,則支援) 。 請注意,AF_位址系列和PF_通訊協定系列常數的值 (相同,例如 AF_UNSPEC和 PF_UNSPEC) ,因此可以使用任一常數。

下表列出位址系列的常見值,但可能有許多其他值。

意義
AF_UNSPEC
0
未指定位址系列。
AF_INET
2
因特網通訊協定第 4 版 (IPv4) 位址系列。
AF_NETBIOS
17
NetBIOS 位址系列。 只有在已安裝 NetBIOS 的 Windows Sockets 提供者時,才支援此位址系列。
AF_INET6
23
因特網通訊協定第 6 版 (IPv6) 位址系列。
AF_IRDA
26
Infrared Data Association (IrDA) 位址系列。 只有在計算機已安裝基礎結構埠和驅動程式時,才支援此位址系列。
AF_BTH
32
藍牙位址系列。 只有在 Windows Server 2003 或更新版本上安裝藍牙適配卡時,才支援此位址系列。

ai_socktype

類型: int

套接字類型。 套接字類型的可能值定義在 Winsock2.h 包含檔案中。

下表列出 Windows Sockets 2 支援的套接字型態可能值:

意義
SOCK_STREAM
1
使用 OOB 數據傳輸機制,提供循序、可靠、雙向、以連線為基礎的位元組數據流。 針對因特網位址系列使用傳輸控制通訊協定 (TCP) (AF_INETAF_INET6) 。 如果 ai_family 成員 是AF_IRDA則SOCK_STREAM 是唯一支援的套接字類型。
SOCK_DGRAM
2
支持數據報,這些數據報是無連接、不可靠的固定 (通常很小) 最大長度。 針對因特網位址系列 (AF_INET或AF_INET6) ,使用使用者數據報通訊協定 (UDP) 。
SOCK_RAW
3
提供原始套接字,可讓應用程式操作下一層通訊協議標頭。 若要操作 IPv4 標頭,必須在套接字上設定 IP_HDRINCL 套接字選項。 若要操作 IPv6 標頭,必須在套接字上設定 IPV6_HDRINCL 套接字選項。
SOCK_RDM
4
提供可靠的訊息數據報。 此類型的範例是 Windows 中的「實用一般多播」 (PGM) 多播通訊協議實作,通常稱為 可靠的多播程序設計
SOCK_SEQPACKET
5
根據數據報提供虛擬數據流封包。
 

在 Windows Sockets 2 中,引進了新的套接字類型。 應用程式可以透過 WSAEnumProtocols 函式動態探索每個可用傳輸通訊協議的屬性。 因此,應用程式可以判斷位址系列可能的套接字類型和通訊協定選項,並在指定此參數時使用此資訊。 Winsock2.hWs2def.h 頭檔中的套接字類型定義會定期更新,因為定義了新的套接字類型、位址系列和通訊協定。

在 Windows Sockets 1.1 中,唯一可能的套接字類型是 SOCK_DATAGRAMSOCK_STREAM

ai_protocol

類型: int

通訊協定類型。 可能的選項是指定的位址系列和套接字類型所特有。 ai_protocol的可能值定義於 Winsock2.hWsrm.h 頭檔中。

在針對 Windows Vista 和更新版本發行的 Windows SDK 上,頭檔的組織已變更,而且此成員可以是 Ws2def.h 頭檔中定義的 IPPROTO 列舉類型之一值。 請注意, Ws2def.h 頭文件會自動包含在 Winsock2.h 中,不應直接使用。

如果為 ai_protocol指定 0 的值,則呼叫端不想要指定通訊協定,而服務提供者會選擇要使用的 ai_protocol 。 對於 IPv4 和 IPv6 以外的通訊協定, 請將ai_protocol 設定為零。

下表列出 ai_protocol 成員的常見值,但可能有許多其他值。

意義
IPPROTO_TCP
6
傳輸控制通訊協定 (TCP) 。 當 ai_family 成員 AF_INETAF_INET6ai_socktype 成員 SOCK_STREAM時,這是可能的值。
IPPROTO_UDP
17
用戶數據報通訊協定 (UDP) 。 當 ai_family 成員 AF_INETAF_INET6類型 參數 SOCK_DGRAM時,這是可能的值。
IPPROTO_RM
113
可靠多播的PGM通訊協定。 當 ai_family 成員 AF_INETai_socktype 成員 SOCK_RDM時,這是可能的值。 在針對 Windows Vista 和更新版本發行的 Windows SDK 上,這個值也稱為IPPROTO_PGM
 

如果 ai_family 成員 是AF_IRDA,則 ai_protocol 必須是0。

ai_addrlen

類型: size_t

ai_addr成員所指向之緩衝區的長度,以位元組為單位。

ai_canonname

類型: PCTSTR

主機的正式名稱。

ai_addr

類型: 結構 sockaddr*

sockaddr 結構的指標。 每個傳回 addrinfoex 結構中的ai_addr成員會指向填入的套接字地址結構。 每個傳回 addrinfoex 結構的長度,以位元組為單位,都會在 ai_addrlen 成員中指定。

ai_blob

類型: void*

數據指標,用來傳回與位址清單以外的名稱相關聯的提供者特定命名空間資訊。 ai_blob所指向之緩衝區的長度,以位元組為單位,必須在ai_bloblen成員中指定。

ai_bloblen

類型: size_t

ai_blob成員的長度,以位元組為單位。

ai_provider

類型: LPGUID

特定命名空間提供者之 GUID 的指標。

ai_next

類型: 結構 addrinfoex*

連結清單中的下一個結構的指標。 此參數會在連結清單的最後一個 addrinfoex 結構中設定為 NULL

備註

addrinfoex 結構是由 GetAddrInfoEx 函式用來保存主機地址資訊。 addrinfoex 結構是 addrinfoaddrinfoW 結構的增強版本。 額外的結構成員適用於 Blob 資料和命名空間提供者的 GUID。 Blob 資料可用來傳回與名稱相關聯的其他提供者特定命名空間資訊。 ai_blob成員中的數據格式是特定命名空間提供者特有的。 目前, NS_EMAIL 命名空間提供者會使用 Blob 數據來提供其他資訊。

addrinfoex 結構是搭配 GetAddrInfoEx 函式使用的 addrinfoaddrinfoW 結構的增強版本。 GetAddrInfoEx 函式允許指定命名空間提供者來解析查詢。 為了與 IPv6 和 IPv4 通訊協定搭配使用,名稱解析可以是域名系統 (DNS) 、本機 主機 檔案、電子郵件提供者 (NS_EMAIL 命名空間) 或其他命名機制。

定義 UNICODE 或_UNICODE時,addrinfoex 會定義為 addrinfoexW,這是這個結構的 Unicode 版本。 字串參數會定義至 PWSTR 數據類型,並使用 addrinfoexW 結構。

未定義 UNICODE 或_UNICODE時,addrinfoex 會定義為 addrinfoexA這是這個結構的 ANSI 版本。 字串參數屬於 PCSTR 數據類型,並使用 addrinfoexA 結構。

成功呼叫 GetAddrInfoEx 時,會將 addrinfoex 結構的連結清單傳回至 GetAddrInfoEx 函式的 ppResult 參數中。 您可以依照每個傳回 addrinfoex 結構的ai_next成員中提供的指標來處理清單直到遇到 NULL 指標為止。 在每個傳回 的 addrinfoex 結構中, ai_familyai_socktypeai_protocol 成員會對應到 套接字WSASocket 函數調用中的個別自變數。 此外,每個傳回 addrinfoex 結構中的ai_addr成員都會指向填入的套接字地址結構,其ai_addrlen成員中指定的長度。

範例

下列範例示範如何使用 addrinfoex 結構。


#ifndef UNICODE
#define UNICODE
#endif

#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif

#include <windows.h>
#include <winsock2.h>
#include <ws2tcpip.h>
#include <stdio.h>

#pragma comment(lib, "Ws2_32.lib")

int __cdecl wmain(int argc, wchar_t ** argv)
{
//--------------------------------
// Declare and initialize variables.
    WSADATA wsaData;
    int iResult;

    ADDRINFOEX *result = NULL;
    ADDRINFOEX *ptr = NULL;
    ADDRINFOEX hints;

    DWORD dwRetval = 0;
    int i = 1;

    DWORD dwNamespace = NS_DNS;
    LPGUID lpNspid = NULL;

    struct sockaddr_in *sockaddr_ipv4;
    struct sockaddr_in6 *sockaddr_ipv6;
//    LPSOCKADDR sockaddr_ip;

    wchar_t ipstringbuffer[46];

    // Validate the parameters
    if (argc != 3) {
        wprintf(L"usage: %ws <hostname> <servicename>\n", argv[0]);
        wprintf(L"       provides protocol-independent translation\n");
        wprintf(L"       from a host name to an IP address\n");
        wprintf(L"%ws example usage\n", argv[0]);
        wprintf(L"   %ws www.contoso.com 0\n", argv[0]);
        return 1;
    }
    // Initialize Winsock
    iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
    if (iResult != 0) {
        wprintf(L"WSAStartup failed: %d\n", iResult);
        return 1;
    }
//--------------------------------
// Setup the hints address info structure
// which is passed to the GetAddrInfoW() function
    memset(&hints, 0, sizeof (hints));
    hints.ai_family = AF_UNSPEC;
    hints.ai_socktype = SOCK_STREAM;
    hints.ai_protocol = IPPROTO_TCP;

    wprintf(L"Calling GetAddrInfoEx with following parameters:\n");
    wprintf(L"\tName = %ws\n", argv[1]);
    wprintf(L"\tServiceName (or port) = %ws\n\n", argv[2]);

//--------------------------------
// Call GetAddrInfoEx(). If the call succeeds,
// the aiList variable will hold a linked list
// of ADDRINFOEX structures containing response
// information about the host
    dwRetval = GetAddrInfoEx(argv[1], argv[2],
                             dwNamespace, lpNspid, &hints, &result,
                             NULL, NULL, NULL, NULL);

    if (dwRetval != 0) {
        wprintf(L"GetAddrInfoEx failed with error: %d\n", dwRetval);
        WSACleanup();
        return 1;
    }
    wprintf(L"GetAddrInfoEx returned success\n");

    // Retrieve each address and print out the hex bytes
    for (ptr = result; ptr != NULL; ptr = ptr->ai_next) {

        wprintf(L"GetAddrInfoEx response %d\n", i++);
        wprintf(L"\tFlags: 0x%x\n", ptr->ai_flags);
        wprintf(L"\tFamily: ");
        switch (ptr->ai_family) {
        case AF_UNSPEC:
            wprintf(L"Unspecified\n");
            break;
        case AF_INET:
            wprintf(L"AF_INET (IPv4)\n");
            // the InetNtop function is available on Windows Vista and later
            sockaddr_ipv4 = (struct sockaddr_in *) ptr->ai_addr;
            wprintf(L"\tIPv4 address %ws\n",
                    InetNtop(AF_INET, &sockaddr_ipv4->sin_addr, ipstringbuffer,
                             46));

            // We could also use the WSAAddressToString function
            // sockaddr_ip = (LPSOCKADDR) ptr->ai_addr;
            // The buffer length is changed by each call to WSAAddresstoString
            // So we need to set it for each iteration through the loop for safety
            // ipbufferlength = 46;
            // iRetval = WSAAddressToString(sockaddr_ip, (DWORD) ptr->ai_addrlen, NULL, 
            //    ipstringbuffer, &ipbufferlength );
            // if (iRetval)
            //    wprintf(L"WSAAddressToString failed with %u\n", WSAGetLastError() );
            // else    
            //    wprintf(L"\tIPv4 address %ws\n", ipstringbuffer);
            break;
        case AF_INET6:
            wprintf(L"AF_INET6 (IPv6)\n");
            // the InetNtop function is available on Windows Vista and later
            sockaddr_ipv6 = (struct sockaddr_in6 *) ptr->ai_addr;
            wprintf(L"\tIPv6 address %ws\n",
                    InetNtop(AF_INET6, &sockaddr_ipv6->sin6_addr,
                             ipstringbuffer, 46));

            // We could also use WSAAddressToString which also returns the scope ID
            // sockaddr_ip = (LPSOCKADDR) ptr->ai_addr;
            // The buffer length is changed by each call to WSAAddresstoString
            // So we need to set it for each iteration through the loop for safety
            // ipbufferlength = 46;
            //iRetval = WSAAddressToString(sockaddr_ip, (DWORD) ptr->ai_addrlen, NULL, 
            //    ipstringbuffer, &ipbufferlength );
            //if (iRetval)
            //    wprintf(L"WSAAddressToString failed with %u\n", WSAGetLastError() );
            //else    
            //    wprintf(L"\tIPv6 address %ws\n", ipstringbuffer);
            break;
        default:
            wprintf(L"Other %ld\n", ptr->ai_family);
            break;
        }
        wprintf(L"\tSocket type: ");
        switch (ptr->ai_socktype) {
        case 0:
            wprintf(L"Unspecified\n");
            break;
        case SOCK_STREAM:
            wprintf(L"SOCK_STREAM (stream)\n");
            break;
        case SOCK_DGRAM:
            wprintf(L"SOCK_DGRAM (datagram) \n");
            break;
        case SOCK_RAW:
            wprintf(L"SOCK_RAW (raw) \n");
            break;
        case SOCK_RDM:
            wprintf(L"SOCK_RDM (reliable message datagram)\n");
            break;
        case SOCK_SEQPACKET:
            wprintf(L"SOCK_SEQPACKET (pseudo-stream packet)\n");
            break;
        default:
            wprintf(L"Other %ld\n", ptr->ai_socktype);
            break;
        }
        wprintf(L"\tProtocol: ");
        switch (ptr->ai_protocol) {
        case 0:
            wprintf(L"Unspecified\n");
            break;
        case IPPROTO_TCP:
            wprintf(L"IPPROTO_TCP (TCP)\n");
            break;
        case IPPROTO_UDP:
            wprintf(L"IPPROTO_UDP (UDP) \n");
            break;
        default:
            wprintf(L"Other %ld\n", ptr->ai_protocol);
            break;
        }
        wprintf(L"\tLength of this sockaddr: %d\n", ptr->ai_addrlen);
        wprintf(L"\tCanonical name: %s\n", ptr->ai_canonname);
    }

    FreeAddrInfoEx(result);
    WSACleanup();

    return 0;
}


注意 請確定開發環境以最新版 的 Ws2tcpip.h 為目標,分別包含 ADDRINFOEXGetAddrInfoEx 的結構和函式定義。
 

規格需求

需求
最低支援的用戶端 Windows Vista [僅限傳統型應用程式]
最低支援的伺服器 Windows Server 2008 [僅限傳統型應用程式]
標頭 ws2def.h (包含 Windows Server 2012、Windows 7 Windows Server 2008 R2)

另請參閱

GetAddrInfoEx

addrinfo

addrinfoW