ADDRINFOA 結構 (ws2def.h)

getaddrinfo 函式會使用 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;
} ADDRINFOA, *PADDRINFOA;

成員

ai_flags

類型: int

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

ai_flags成員的支援值定義於 Windows 7 和更新版本 Windows SDK 上的 Ws2def.h 頭檔中。 這些值定義於 Windows Server 2008 和 Windows Vista Windows SDK 上的 Ws2tcpip.h 頭檔中。 這些值定義於 Windows Server 2003 平臺 SDK 和 Windows XP 上的 Ws2tcpip.h 頭檔中。 ai_flags 成員的支援 值可以是下列選項的組合。

意義
AI_PASSIVE
0x01
套接字位址將用於對 bind 函式的呼叫。
AI_CANONNAME
0x02
標準名稱會在第一 個ai_canonname 成員中傳回。
AI_NUMERICHOST
0x04
傳遞至 getaddrinfo 函式的 nodename 參數必須是數值字串。
AI_ALL
0x0100
如果設定此位,則會針對具有 AI_V4MAPPED的 IPv6 位址和 IPv4 位址提出要求。

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

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

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

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

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

AI_NON_AUTHORITATIVE
0x04000
地址資訊可以是來自非權威命名空間提供者。

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

AI_SECURE
0x08000
地址信息來自安全通道。

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

AI_RETURN_PREFERRED_NAMES
0x010000
地址資訊適用於使用者的慣用名稱。

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

AI_FQDN
0x00020000
如果指定單一名稱 (單一卷標 ) ,getaddrinfo 會傳回最終解析名稱的完整功能變數名稱。 完整功能變數名稱會在 ai_canonname 成員中傳回。

這不同於 AI_CANONNAME 位旗標,此旗標會傳回在 DNS 中註冊的正式名稱,可能與一般名稱解析為的完整功能變數名稱不同。

只能設定其中一個 AI_FQDNAI_CANONNAME 位。 如果兩個旗標都出現EAI_BADFLAGS,getaddrinfo 函式將會失敗。

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

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

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

ai_family

類型: int

位址系列。 位址系列的可能值定義在 Winsock2.h 頭檔中。

在 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

類型: char*

主機的正式名稱。

ai_addr

類型: 結構 sockaddr*

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

ai_next

類型: struct addrinfo*

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

備註

ANSI getaddrinfo 函式會使用 addrinfo 結構來保存主機地址資訊。

addrinfoW 結構是 Unicode GetAddrInfoW 函式所使用的這個結構版本。

Ws2tcpip.h 頭檔中的宏會定義 ADDRINFOT 結構和 GetAddrInfo 的混合大小寫函式名稱。 GetAddrInfo 函式應該使用 TCHAR 型別指標的 nodenameservname 參數,以及 ADDRINFOT 型別指標的提示res 參數來呼叫。 未定義 UNICODE 或_UNICODE時, ADDRINFOT 會定義至 addrinfo 結構,並將 GetAddrInfo 定義為 getaddrinfo,這是此函式的 ANSI 版本。 定義 UNICODE 或_UNICODE時,ADDRINFOT 會定義至 addrinfoW 結構,並將 GetAddrInfo 定義為 GetAddrInfoW,這是此函式的 Unicode 版本。

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

支援舊版 Windows 上的 getaddrinfo 和 addrinfo 結構

使用 addrinfo 結構的 getaddrinfo 函式已新增至 Windows XP 和更新版本的 Ws2_32.dlladdrinfo 結構定義於 Windows XP 和更新版本平臺 SDK 隨附的 Ws2tcpip.h 頭檔中,以及針對 Windows Vista 和更新版本發行的 Windows SDK。

若要在舊版 Windows (Windows 2000) 上執行使用 getaddrinfo 函式和 addrinfo 結構的應用程式,您需要包含 Ws2tcpip.hWspiapi.h 檔案。 新增 Wspiapi.h 包含檔案時, getaddrinfo 函式會定義至 Wspiapi.h 檔案中的 WspiapiGetAddrInfo 內嵌函式。 在運行時間,WspiapiGetAddrInfo 函式會實作,如此一來,如果 Ws2_32.dllWship6.dll (Windows 200) 0 Technical Preview 中的 getaddrinfo 檔案不包含 getaddrinfo,則會根據 Wspiapi.h 頭檔中的程式代碼實作 getaddrinfo 版本。 此內嵌程式代碼將用於原本不支援 getaddrinfo 函式的舊版 Windows 平臺上。

安裝適用於 Windows 2000 的 IPv6 技術預覽版時,Windows 2000 支援 IPv6 通訊協定。 否則,在 Windows XP 之前的 Windows 版本上, getaddrinfo 支援僅限於處理 IPv4 名稱解析。

使用 addrinfoW 結構的 GetAddrInfoW 函式是 getaddrinfo 函式的 Unicode 版本,以及相關聯的 addrinfo 結構。 GetAddrInfoW 函式已新增至 Windows XP service Pack 2 (SP2 ) 中的Ws2_32.dllGetAddrInfoW 函式和 addrinfoW 結構不能用於 Windows XP 與 SP2 之前的 Windows 版本。

範例

下列程式代碼範例示範 addrinfo 結構的用法。


#undef UNICODE

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

// link with Ws2_32.lib
#pragma comment(lib, "Ws2_32.lib")

int __cdecl main(int argc, char **argv)
{

    //-----------------------------------------
    // Declare and initialize variables
    WSADATA wsaData;
    int iResult;
    INT iRetval;

    DWORD dwRetval;

    int i = 1;
    
    struct addrinfo *result = NULL;
    struct addrinfo *ptr = NULL;
    struct addrinfo hints;

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

    char ipstringbuffer[46];
    DWORD ipbufferlength = 46;

    // Validate the parameters
    if (argc != 3) {
        printf("usage: %s <hostname> <servicename>\n", argv[0]);
        printf("       provides protocol-independent translation\n");
        printf("       from an ANSI host name to an IP address\n");
        printf("%s example usage\n", argv[0]);
        printf("   %s www.contoso.com 0\n", argv[0]);
        return 1;
    }

    // Initialize Winsock
    iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
    if (iResult != 0) {
        printf("WSAStartup failed: %d\n", iResult);
        return 1;
    }

    //--------------------------------
    // Setup the hints address info structure
    // which is passed to the getaddrinfo() function
    ZeroMemory( &hints, sizeof(hints) );
    hints.ai_family = AF_UNSPEC;
    hints.ai_socktype = SOCK_STREAM;
    hints.ai_protocol = IPPROTO_TCP;

    printf("Calling getaddrinfo with following parameters:\n");
    printf("\tnodename = %s\n", argv[1]);
    printf("\tservname (or port) = %s\n\n", argv[2]);
    
//--------------------------------
// Call getaddrinfo(). If the call succeeds,
// the result variable will hold a linked list
// of addrinfo structures containing response
// information
    dwRetval = getaddrinfo(argv[1], argv[2], &hints, &result);
    if ( dwRetval != 0 ) {
        printf("getaddrinfo failed with error: %d\n", dwRetval);
        WSACleanup();
        return 1;
    }

    printf("getaddrinfo returned success\n");
    
    // Retrieve each address and print out the hex bytes
    for(ptr=result; ptr != NULL ;ptr=ptr->ai_next) {

        printf("getaddrinfo response %d\n", i++);
        printf("\tFlags: 0x%x\n", ptr->ai_flags);
        printf("\tFamily: ");
        switch (ptr->ai_family) {
            case AF_UNSPEC:
                printf("Unspecified\n");
                break;
            case AF_INET:
                printf("AF_INET (IPv4)\n");
                sockaddr_ipv4 = (struct sockaddr_in *) ptr->ai_addr;
                printf("\tIPv4 address %s\n",
                    inet_ntoa(sockaddr_ipv4->sin_addr) );
                break;
            case AF_INET6:
                printf("AF_INET6 (IPv6)\n");
                // the InetNtop function is available on Windows Vista and later
                // sockaddr_ipv6 = (struct sockaddr_in6 *) ptr->ai_addr;
                // printf("\tIPv6 address %s\n",
                //    InetNtop(AF_INET6, &sockaddr_ipv6->sin6_addr, ipstringbuffer, 46) );
                
                // We use WSAAddressToString since it is supported on Windows XP and later
                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)
                    printf("WSAAddressToString failed with %u\n", WSAGetLastError() );
                else    
                    printf("\tIPv6 address %s\n", ipstringbuffer);
                break;
            case AF_NETBIOS:
                printf("AF_NETBIOS (NetBIOS)\n");
                break;
            default:
                printf("Other %ld\n", ptr->ai_family);
                break;
        }
        printf("\tSocket type: ");
        switch (ptr->ai_socktype) {
            case 0:
                printf("Unspecified\n");
                break;
            case SOCK_STREAM:
                printf("SOCK_STREAM (stream)\n");
                break;
            case SOCK_DGRAM:
                printf("SOCK_DGRAM (datagram) \n");
                break;
            case SOCK_RAW:
                printf("SOCK_RAW (raw) \n");
                break;
            case SOCK_RDM:
                printf("SOCK_RDM (reliable message datagram)\n");
                break;
            case SOCK_SEQPACKET:
                printf("SOCK_SEQPACKET (pseudo-stream packet)\n");
                break;
            default:
                printf("Other %ld\n", ptr->ai_socktype);
                break;
        }
        printf("\tProtocol: ");
        switch (ptr->ai_protocol) {
            case 0:
                printf("Unspecified\n");
                break;
            case IPPROTO_TCP:
                printf("IPPROTO_TCP (TCP)\n");
                break;
            case IPPROTO_UDP:
                printf("IPPROTO_UDP (UDP) \n");
                break;
            default:
                printf("Other %ld\n", ptr->ai_protocol);
                break;
        }
        printf("\tLength of this sockaddr: %d\n", ptr->ai_addrlen);
        printf("\tCanonical name: %s\n", ptr->ai_canonname);
    }

    freeaddrinfo(result);
    WSACleanup();

    return 0;
}

規格需求

需求
最低支援的用戶端 Windows 2000 Professional [僅限傳統型應用程式]
最低支援的伺服器 Windows 2000 Server [僅限桌面應用程式]
標頭 ws2def.h

另請參閱

GetAddrInfoW

WSAEnumProtocols

addrinfoW

bind

getaddrinfo

sockaddr