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
如果 IPv6 地址的 GetAddrInfoW 请求失败,则会针对 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 成员中返回。

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

只能设置一个 AI_FQDN 位和 AI_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 地址系列格式。 AF_NETBIOS用于 NetBIOS 的地址系列 ( 的其他选项,例如,如果安装了地址系列的 Windows 套接字服务提供程序,则支持) 。 请注意,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 包含文件中定义。

下表列出了 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

协议类型。 可能的选项特定于指定的地址系列和套接字类型。 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_INET或AF_INET6ai_socktype成员SOCK_STREAM时,此值是可能的
IPPROTO_UDP
17
用户数据报协议 (UDP) 。 当ai_family成员AF_INET或AF_INET6类型参数SOCK_DGRAM时,此值可能为
IPPROTO_RM
113
可靠多播的 PGM 协议。 当ai_family成员AF_INET且ai_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

类型: struct sockaddr*

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

ai_next

类型: struct addrinfoW*

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

注解

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

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

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

成功调用 GetAddrInfoW 后,将在传递给 GetAddrInfoW 函数的 ppResult 参数中返回 ADDRINFOW 结构的链接列表。 可以通过遵循每个返回的 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;
}

要求

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

另请参阅

GetAddrInfoEx

GetAddrInfoW

WSAEnumProtocols

addrinfo

addrinfoex

addrinfoex2

getaddrinfo

sockaddr