ADDRINFOW 结构 (ws2def.h)

GetAddrInfoW 函数使用 addrinfoW 结构来保存主机地址信息。

语法

typedef struct addrinfoW {
  int              ai_flags;
  int              ai_family;
  int              ai_socktype;
  int              ai_protocol;
  size_t           ai_addrlen;
  PWSTR            ai_canonname;
  struct sockaddr  *ai_addr;
  struct addrinfoW *ai_next;
} ADDRINFOW, *PADDRINFOW;

成员

ai_flags

类型:int

指示 GetAddrInfoW 函数中使用的选项的标志。

ai_flags 成员支持的值在 Winsock2.h 头文件中定义,可以是下表中列出的选项的组合。

价值 意义
AI_PASSIVE
0x01
套接字地址将在调用 绑定 函数时使用。
AI_CANONNAME
0x02
规范名称在第一个 ai_canonname 成员中返回。
AI_NUMERICHOST
0x04
传递给 GetAddrInfoW 函数的 nodename 参数必须是数值字符串。
AI_ALL
0x0100
如果设置了此位,则会为具有 AI_V4MAPPED的 IPv6 地址和 IPv4 地址发出请求。

Windows Vista 及更高版本支持此选项。

AI_ADDRCONFIG
0x0400
仅当配置全局地址时,GetAddrInfoW 才会解析。 IPv6 和 IPv4 环回地址不被视为有效的全局地址。 此选项仅在 Windows Vista 及更高版本上受支持。
AI_V4MAPPED
0x0800
如果 GetAddrInfoW IPv6 地址请求失败,则会对 IPv4 地址发出名称服务请求,并且这些地址转换为 IPv4 映射的 IPv6 地址格式。

Windows Vista 及更高版本支持此选项。

AI_NON_AUTHORITATIVE
0x04000
地址信息可以来自非权威命名空间提供程序。

此选项仅在 Windows Vista 及更高版本上受 NS_EMAIL 命名空间支持。

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

此选项仅在 Windows Vista 及更高版本上受 NS_EMAIL 命名空间支持。

AI_RETURN_PREFERRED_NAMES
0x010000
地址信息用于用户的首选名称。

此选项仅在 Windows Vista 及更高版本上受 NS_EMAIL 命名空间支持。

AI_FQDN
0x00020000
如果指定了平面名称(单个标签),GetAddrInfoW 将返回名称最终解析为的完全限定域名。 完全限定的域名在 ai_canonname 成员中返回。

这不同于返回 DNS 中注册的规范名称的 AI_CANONNAME 位标志,该标志可能与平面名称解析为的完全限定域名不同。

只能设置其中一个 AI_FQDNAI_CANONNAME 位。 如果两个标志都存在 EAI_BADFLAGS,则 GetAddrInfoW 函数将失败。

Windows 7、Windows Server 2008 R2 及更高版本支持此选项。

AI_FILESERVER
0x00040000
命名空间提供程序提示正在文件共享方案中使用要查询的主机名。 命名空间提供程序可能会忽略此提示。

Windows 7、Windows Server 2008 R2 及更高版本支持此选项。

AI_DISABLE_IDN_ENCODING
0x00080000
getAddrInfoW 函数调用的名称解析函数中使用 Punycode 禁用自动国际域名编码。

Windows 8、Windows Server 2012 及更高版本支持此选项。

ai_family

类型:int

地址系列。 地址系列的可能值在 Winsock2.h 头文件中定义。

在适用于 Windows Vista 及更高版本的 Windows SDK 上,头文件的组织已更改,地址系列的可能值在 Ws2def.h 头文件中定义。 请注意,Ws2def.h 头文件自动包含在 Winsock2.h中,不应直接使用。

当前支持的值是 AF_INETAF_INET6,它们是 IPv4 和 IPv6 的 Internet 地址系列格式。 如果安装了地址系列的 Windows 套接字服务提供商,则支持地址系列的其他选项(例如,用于 NetBIOS 的AF_NETBIOS)。 请注意,AF_地址系列和PF_协议系列常量的值相同(例如,AF_UNSPECPF_UNSPEC),因此可以使用任一常量。

下表列出了地址系列的公共值,尽管可能有多个其他值。

价值 意义
AF_UNSPEC
0
未指定地址系列。
AF_INET
2
Internet 协议版本 4 (IPv4) 地址系列。
AF_NETBIOS
17
NetBIOS 地址系列。 仅当安装了适用于 NetBIOS 的 Windows 套接字提供程序时,才支持此地址系列。
AF_INET6
23
Internet 协议版本 6 (IPv6) 地址系列。
AF_IRDA
26
红外数据关联(IrDA)地址系列。 仅当计算机安装了红外端口和驱动程序时,才支持此地址系列。
AF_BTH
32
蓝牙地址系列。 仅当蓝牙适配器安装在 Windows Server 2003 或更高版本上时,才支持此地址系列。

ai_socktype

类型:int

套接字类型。 套接字类型的可能值在 Winsock2.h include 文件中定义。

下表列出了 Windows 套接字 2 支持的套接字类型的可能值。

价值 意义
SOCK_STREAM
1
使用 OOB 数据传输机制提供基于连接的有序双向字节流。 将传输控制协议(TCP)用于 Internet 地址系列(AF_INETAF_INET6)。 如果 ai_family 成员 AF_IRDA,则 SOCK_STREAM 是唯一受支持的套接字类型。
SOCK_DGRAM
2
支持数据报,这些数据报是固定(通常较小)最大长度的无连接、不可靠的缓冲区。 将用户数据报协议(UDP)用于 Internet 地址系列(AF_INETAF_INET6)。
SOCK_RAW
3
提供一个原始套接字,允许应用程序作下一层协议标头。 若要作 IPv4 标头,必须在套接字上设置 IP_HDRINCL 套接字选项。 若要作 IPv6 标头,必须在套接字上设置 IPV6_HDRINCL 套接字选项。
SOCK_RDM
4
提供可靠的消息数据报。 此类型的一个示例是 Windows 中的实用常规多播(PGM)多播协议实现,通常称为 可靠的多播编程
SOCK_SEQPACKET
5
提供基于数据报的伪流数据包。
 

在 Windows 套接字 2 中,引入了新的套接字类型。 应用程序可以通过 WSAEnumProtocols 函数动态发现每个可用传输协议的属性。 因此,应用程序可以确定地址系列可能的套接字类型和协议选项,并在指定此参数时使用此信息。 Winsock2.hWs2def.h 头文件中的套接字类型定义将定期更新,因为定义了新的套接字类型、地址系列和协议。

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

ai_protocol

类型:int

协议类型。 可能的选项特定于指定的地址系列和套接字类型。 Winsock2.hWsrm.h 头文件中定义了 ai_protocol 的可能值。

在适用于 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

类型:PWSTR

主机的规范名称。

ai_addr

类型:结构 sockaddr*

指向 sockaddr 结构的指针。 每个返回 ADDRINFOW 结构中的 ai_addr 成员指向填充的套接字地址结构。 ai_addrlen 成员中指定了每个返回 ADDRINFOW 结构的长度(以字节为单位)。

ai_next

类型:结构 addrinfoW*

指向链接列表中的下一个结构的指针。 此参数设置为在链接列表的最后一 addrinfoW 结构中 NULL

言论

Unicode GetAddrInfoW 函数使用 addrinfoW 结构来保存主机地址信息。

addrinfo 结构是 ANSI getaddrinfo 函数使用的此结构的 ANSI 版本。

Ws2tcpip.h 头文件中的宏定义 ADDRINFOT 结构和 GetAddrInfo的混合大小写函数名称。 GetAddrInfo 函数应使用 nodenameservname 参数调用 TCHAR 类型的指针以及 提示 参数 ADDRINFOT。 定义 UNICODE 或_UNICODE时,ADDRINFOT 定义为 addrinfoW 结构,GetAddrInfo 定义为 GetAddrInfoW(此函数的 Unicode 版本)。 如果未定义 UNICODE 或_UNICODE,ADDRINFOT 定义为 addrinfo 结构,GetAddrInfo 定义为 getaddrinfo,此函数的 ANSI 版本。

成功调用 GetAddrInfoW后,ADDRINFOW 结构的链接列表会在传递给 GetAddrInfoW 函数的 ppResult 参数中返回。 可以按照每个返回 ADDRINFOW 结构的 ai_next 成员中提供的指针来处理列表,直到遇到 NULL 指针。 在每个返回 ADDRINFOW 结构中,ai_familyai_socktypeai_protocol 成员对应于 套接字WSASocket 函数调用中的相应参数。 此外,每个返回 ADDRINFOW 结构中的 ai_addr 成员指向填充的套接字地址结构,其 ai_addrlen 成员中指定的长度。

例子

下面的代码示例演示如何使用 addrinfoW 结构。

#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;

    ADDRINFOW *result = NULL;
    ADDRINFOW *ptr = NULL;
    ADDRINFOW hints;

    DWORD dwRetval = 0;
    int i = 1;

    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 GetAddrInfoW with following parameters:\n");
    wprintf(L"\tName = %ws\n", argv[1]);
    wprintf(L"\tServiceName (or port) = %ws\n\n", argv[2]);

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

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

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

        wprintf(L"GetAddrInfoW 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);
    }

    FreeAddrInfo(result);
    WSACleanup();

    return 0;
}

要求

要求 价值
最低支持的客户端 具有 SP2 的 Windows Vista、Windows XP [仅限桌面应用]
支持的最低服务器 Windows Server 2003 [仅限桌面应用]
标头 ws2def.h (包括 Windows Server 2012、Windows 7 Windows Server 2008 R2)

另请参阅

GetAddrInfoEx

GetAddrInfoW

WSAEnumProtocols

addrinfo

addrinfoex

addrinfoex2

getaddrinfo

sockaddr