GetAdaptersAddresses 函数 (iphlpapi.h)

GetAdaptersAddresses 函数检索与本地计算机上的适配器关联的地址。

语法

IPHLPAPI_DLL_LINKAGE ULONG GetAdaptersAddresses(
  [in]      ULONG                 Family,
  [in]      ULONG                 Flags,
  [in]      PVOID                 Reserved,
  [in, out] PIP_ADAPTER_ADDRESSES AdapterAddresses,
  [in, out] PULONG                SizePointer
);

parameters

[in] Family

要检索的地址的地址系列。 此参数须为下列值之一。

含义
AF_UNSPEC
0
返回与启用了 IPv4 或 IPv6 的适配器关联的 IPv4 和 IPv6 地址。
AF_INET
2
仅返回与启用了 IPv4 的适配器关联的 IPv4 地址。
AF_INET6
23
仅返回与启用了 IPv6 的适配器关联的 IPv6 地址。

[in] Flags

要检索的地址类型。 可能的值在 Iptypes.h 头文件中定义。 请注意, Iptypes.h 头文件会自动包含在 Iphlpapi.h 中,永远不应直接使用。

此参数是以下值的组合。 如果此参数为零,则将返回单播、任意广播和多播 IP 地址。

含义
GAA_FLAG_SKIP_UNICAST
0x0001
不要返回单播地址。
GAA_FLAG_SKIP_ANYCAST
0x0002
不要返回 IPv6 任何广播地址。
GAA_FLAG_SKIP_MULTICAST
0x0004
不要返回多播地址。
GAA_FLAG_SKIP_DNS_SERVER
0x0008
不要返回 DNS 服务器的地址。
GAA_FLAG_INCLUDE_PREFIX
0x0010
返回此适配器上的 IP 地址前缀列表。 设置此标志后,将返回 IPv6 和 IPv4 地址的 IP 地址前缀。

具有 SP1 和更高版本的 Windows XP 支持此标志。

GAA_FLAG_SKIP_FRIENDLY_NAME
0x0020
不要返回适配器友好名称。
GAA_FLAG_INCLUDE_WINS_INFO
0x0040
返回 Windows Internet 名称服务的地址 (WINS) 服务器。

Windows Vista 及更高版本支持此标志。

GAA_FLAG_INCLUDE_GATEWAYS
0x0080
返回默认网关的地址。

Windows Vista 及更高版本支持此标志。

GAA_FLAG_INCLUDE_ALL_INTERFACES
0x0100
返回所有 NDIS 接口的地址。

Windows Vista 及更高版本支持此标志。

GAA_FLAG_INCLUDE_ALL_COMPARTMENTS
0x0200
返回所有路由隔离舱中的地址。

此标志当前不受支持,并保留供将来使用。

GAA_FLAG_INCLUDE_TUNNEL_BINDINGORDER
0x0400
返回按隧道绑定顺序排序的适配器地址。 Windows Vista 及更高版本支持此标志。

[in] Reserved

此参数当前未使用,但保留供将来系统使用。 调用应用程序应为此参数传递 NULL

[in, out] AdapterAddresses

指向缓冲区的指针,该缓冲区包含成功返回时 IP_ADAPTER_ADDRESSES 结构的链接列表。

[in, out] SizePointer

指向变量的指针,该变量指定 AdapterAddresses 指向的缓冲区的大小。

返回值

如果函数成功,则返回值 ERROR_SUCCESS (定义为 与 NO_ERROR) 相同的值。

如果函数失败,则返回值为以下错误代码之一。

返回代码 说明
ERROR_ADDRESS_NOT_ASSOCIATED
地址尚未与网络终结点关联。 DHCP 租约信息可用。
ERROR_BUFFER_OVERFLOW
SizePointer 参数指示的缓冲区大小太小,无法保存适配器信息或 AdapterAddresses 参数为 NULLSizePointer 参数返回的指向所需的缓冲区大小,以保存适配器信息。
ERROR_INVALID_PARAMETER
其中一个参数无效。 对于以下任一情况,将返回此错误: SizePointer 参数为 NULLAddress 参数不 AF_INETAF_INET6AF_UNSPEC,或者请求的参数的地址信息大于 ULONG_MAX
ERROR_NOT_ENOUGH_MEMORY
内存资源不足,无法完成操作。
ERROR_NO_DATA
找不到所请求参数的地址。
其他
使用 FormatMessage 获取返回错误的消息字符串。

注解

The
GetAdaptersAddresses 函数可以检索 IPv4 和 IPv6 地址的信息。

地址作为 adapterAddresses 参数指向的缓冲区中IP_ADAPTER_ADDRESSES结构的链接列表返回。 调用 GetAdaptersAddresses 函数的应用程序必须分配返回 AdapterAddresses 参数指向IP_ADAPTER_ADDRESSES结构所需的内存量。 当不再需要这些返回的结构时,应用程序应释放分配的内存。 这可以通过调用 HeapAlloc 函数来分配内存,然后调用 HeapFree 函数来释放分配的内存,如示例代码所示。 只要分配和可用函数使用相同的函数系列,就可以使用其他内存分配和可用函数。

GetAdaptersAddresses 仅作为同步函数调用实现。 GetAdaptersAddresses 函数需要大量的网络资源和时间才能完成,因为必须遍历所有低级别的网络接口表。

可用于确定返回 AdapterAddresses 参数指向的IP_ADAPTER_ADDRESSES结构所需的内存的一种方法是,在第一次调用 GetAdaptersAddresses 函数时传递 SizePointer 参数中指示的缓冲区大小过小,因此函数将失败并ERROR_BUFFER_OVERFLOW。 当返回值 ERROR_BUFFER_OVERFLOW时, SizePointer 参数返回的指向保存适配器信息所需的缓冲区大小。 请注意,如果添加或删除了适配器地址,AdapterAddresses 参数指向的 IP_ADAPTER_ADDRESSES 结构所需的缓冲区大小可以在对 GetAdaptersAddresses 函数的后续调用之间更改。 但是,强烈建议不要使用 GetAdaptersAddresses 函数的此方法。 此方法需要多次调用 GetAdaptersAddresses 函数。

调用 GetAdaptersAddresses 函数的建议方法是预先分配 AdapterAddresses 参数指向的 15KB 工作缓冲区。 在典型计算机上,这大大降低了 GetAdaptersAddresses 函数返回 ERROR_BUFFER_OVERFLOW的可能性,这需要多次调用 GetAdaptersAddresses 函数。 示例代码演示了此使用方法。

在 Windows 10 之前的版本中,可从“网络连接”文件夹控制此函数返回的列表中适配器的显示顺序:从“高级”菜单中选择“高级设置”菜单项。 从Windows 10开始,适配器在列表中出现的顺序由 IPv4 或 IPv6 路由指标确定。

如果设置了GAA_FLAG_INCLUDE_ALL_INTERFACES,则将检索所有 NDIS 适配器,即使与未绑定到 Family 参数中指定的地址系列的适配器关联的地址也是如此。 如果未设置此标志,则仅返回绑定到为 Family 参数中指定的地址系列启用的适配器的地址。

IP_ADAPTER_ADDRESSES结构的大小在 Windows XP 上更改了 Service Pack 1 (SP1) 及更高版本。 已向此结构添加了几个附加成员。 IP_ADAPTER_ADDRESSES结构的大小也在 Windows Vista 及更高版本上进行了更改。 向此结构添加了一些附加成员。 Windows Vista Service Pack 1 (SP1) 及更高版本以及 Windows Server 2008 及更高版本上,IP_ADAPTER_ADDRESSES结构的大小也发生了变化。 向此结构添加了一个附加成员。 AdapterAddresses 参数指向的缓冲区中结构链接列表中返回的 IP_ADAPTER_ADDRESSES 结构的 Length 成员应用于确定正在使用哪个版本的 IP_ADAPTER_ADDRESSES 结构。

GetIpAddrTable 函数检索本地计算机上的接口到 IPv4 地址映射表,并在MIB_IPADDRTABLE结构中返回此信息。

在为 Windows Server 2003 及更早版本发布的平台软件开发工具包 (SDK) 中, GetAdaptersAddresses 函数的返回值定义为 DWORD,而不是 ULONG

SOCKET_ADDRESS 结构用于 AdapterAddresses 参数指向的IP_ADAPTER_ADDRESSES结构中。 在为 Windows Vista 及更高版本发布的 Microsoft Windows 软件开发工具包 (SDK) 中,头文件的组织已更改,SOCKET_ADDRESS结构在 Winsock2.h 头文件自动包含的 Ws2def.h 头文件中定义。 在针对 Windows Server 2003 和 Windows XP 发布的平台 SDK 上, SOCKET_ADDRESS 结构在 Winsock2.h 头文件中声明。 若要使用 IP_ADAPTER_ADDRESSES 结构, Winsock2.h 头文件必须包含在 Iphlpapi.h 头文件之前。

示例

此示例检索与系统关联的适配器 的IP_ADAPTER_ADDRESSES 结构,并打印每个适配器接口的一些成员。

#include <winsock2.h>
#include <iphlpapi.h>
#include <stdio.h>
#include <stdlib.h>

// Link with Iphlpapi.lib
#pragma comment(lib, "IPHLPAPI.lib")

#define WORKING_BUFFER_SIZE 15000
#define MAX_TRIES 3

#define MALLOC(x) HeapAlloc(GetProcessHeap(), 0, (x))
#define FREE(x) HeapFree(GetProcessHeap(), 0, (x))

/* Note: could also use malloc() and free() */

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

    /* Declare and initialize variables */

    DWORD dwRetVal = 0;

    unsigned int i = 0;

    // Set the flags to pass to GetAdaptersAddresses
    ULONG flags = GAA_FLAG_INCLUDE_PREFIX;

    // default to unspecified address family (both)
    ULONG family = AF_UNSPEC;

    LPVOID lpMsgBuf = NULL;

    PIP_ADAPTER_ADDRESSES pAddresses = NULL;
    ULONG outBufLen = 0;
    ULONG Iterations = 0;

    PIP_ADAPTER_ADDRESSES pCurrAddresses = NULL;
    PIP_ADAPTER_UNICAST_ADDRESS pUnicast = NULL;
    PIP_ADAPTER_ANYCAST_ADDRESS pAnycast = NULL;
    PIP_ADAPTER_MULTICAST_ADDRESS pMulticast = NULL;
    IP_ADAPTER_DNS_SERVER_ADDRESS *pDnServer = NULL;
    IP_ADAPTER_PREFIX *pPrefix = NULL;

    if (argc != 2) {
        printf(" Usage: getadapteraddresses family\n");
        printf("        getadapteraddresses 4 (for IPv4)\n");
        printf("        getadapteraddresses 6 (for IPv6)\n");
        printf("        getadapteraddresses A (for both IPv4 and IPv6)\n");
        exit(1);
    }

    if (atoi(argv[1]) == 4)
        family = AF_INET;
    else if (atoi(argv[1]) == 6)
        family = AF_INET6;

    printf("Calling GetAdaptersAddresses function with family = ");
    if (family == AF_INET)
        printf("AF_INET\n");
    if (family == AF_INET6)
        printf("AF_INET6\n");
    if (family == AF_UNSPEC)
        printf("AF_UNSPEC\n\n");

    // Allocate a 15 KB buffer to start with.
    outBufLen = WORKING_BUFFER_SIZE;

    do {

        pAddresses = (IP_ADAPTER_ADDRESSES *) MALLOC(outBufLen);
        if (pAddresses == NULL) {
            printf
                ("Memory allocation failed for IP_ADAPTER_ADDRESSES struct\n");
            exit(1);
        }

        dwRetVal =
            GetAdaptersAddresses(family, flags, NULL, pAddresses, &outBufLen);

        if (dwRetVal == ERROR_BUFFER_OVERFLOW) {
            FREE(pAddresses);
            pAddresses = NULL;
        } else {
            break;
        }

        Iterations++;

    } while ((dwRetVal == ERROR_BUFFER_OVERFLOW) && (Iterations < MAX_TRIES));

    if (dwRetVal == NO_ERROR) {
        // If successful, output some information from the data we received
        pCurrAddresses = pAddresses;
        while (pCurrAddresses) {
            printf("\tLength of the IP_ADAPTER_ADDRESS struct: %ld\n",
                   pCurrAddresses->Length);
            printf("\tIfIndex (IPv4 interface): %u\n", pCurrAddresses->IfIndex);
            printf("\tAdapter name: %s\n", pCurrAddresses->AdapterName);

            pUnicast = pCurrAddresses->FirstUnicastAddress;
            if (pUnicast != NULL) {
                for (i = 0; pUnicast != NULL; i++)
                    pUnicast = pUnicast->Next;
                printf("\tNumber of Unicast Addresses: %d\n", i);
            } else
                printf("\tNo Unicast Addresses\n");

            pAnycast = pCurrAddresses->FirstAnycastAddress;
            if (pAnycast) {
                for (i = 0; pAnycast != NULL; i++)
                    pAnycast = pAnycast->Next;
                printf("\tNumber of Anycast Addresses: %d\n", i);
            } else
                printf("\tNo Anycast Addresses\n");

            pMulticast = pCurrAddresses->FirstMulticastAddress;
            if (pMulticast) {
                for (i = 0; pMulticast != NULL; i++)
                    pMulticast = pMulticast->Next;
                printf("\tNumber of Multicast Addresses: %d\n", i);
            } else
                printf("\tNo Multicast Addresses\n");

            pDnServer = pCurrAddresses->FirstDnsServerAddress;
            if (pDnServer) {
                for (i = 0; pDnServer != NULL; i++)
                    pDnServer = pDnServer->Next;
                printf("\tNumber of DNS Server Addresses: %d\n", i);
            } else
                printf("\tNo DNS Server Addresses\n");

            printf("\tDNS Suffix: %wS\n", pCurrAddresses->DnsSuffix);
            printf("\tDescription: %wS\n", pCurrAddresses->Description);
            printf("\tFriendly name: %wS\n", pCurrAddresses->FriendlyName);

            if (pCurrAddresses->PhysicalAddressLength != 0) {
                printf("\tPhysical address: ");
                for (i = 0; i < (int) pCurrAddresses->PhysicalAddressLength;
                     i++) {
                    if (i == (pCurrAddresses->PhysicalAddressLength - 1))
                        printf("%.2X\n",
                               (int) pCurrAddresses->PhysicalAddress[i]);
                    else
                        printf("%.2X-",
                               (int) pCurrAddresses->PhysicalAddress[i]);
                }
            }
            printf("\tFlags: %ld\n", pCurrAddresses->Flags);
            printf("\tMtu: %lu\n", pCurrAddresses->Mtu);
            printf("\tIfType: %ld\n", pCurrAddresses->IfType);
            printf("\tOperStatus: %ld\n", pCurrAddresses->OperStatus);
            printf("\tIpv6IfIndex (IPv6 interface): %u\n",
                   pCurrAddresses->Ipv6IfIndex);
            printf("\tZoneIndices (hex): ");
            for (i = 0; i < 16; i++)
                printf("%lx ", pCurrAddresses->ZoneIndices[i]);
            printf("\n");

            printf("\tTransmit link speed: %I64u\n", pCurrAddresses->TransmitLinkSpeed);
            printf("\tReceive link speed: %I64u\n", pCurrAddresses->ReceiveLinkSpeed);

            pPrefix = pCurrAddresses->FirstPrefix;
            if (pPrefix) {
                for (i = 0; pPrefix != NULL; i++)
                    pPrefix = pPrefix->Next;
                printf("\tNumber of IP Adapter Prefix entries: %d\n", i);
            } else
                printf("\tNumber of IP Adapter Prefix entries: 0\n");

            printf("\n");

            pCurrAddresses = pCurrAddresses->Next;
        }
    } else {
        printf("Call to GetAdaptersAddresses failed with error: %d\n",
               dwRetVal);
        if (dwRetVal == ERROR_NO_DATA)
            printf("\tNo addresses were found for the requested parameters\n");
        else {

            if (FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
                    FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, 
                    NULL, dwRetVal, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),   
                    // Default language
                    (LPTSTR) & lpMsgBuf, 0, NULL)) {
                printf("\tError: %s", lpMsgBuf);
                LocalFree(lpMsgBuf);
                if (pAddresses)
                    FREE(pAddresses);
                exit(1);
            }
        }
    }

    if (pAddresses) {
        FREE(pAddresses);
    }

    return 0;
}

要求

   
最低受支持的客户端 Windows XP [桌面应用 | UWP 应用]
最低受支持的服务器 Windows Server 2003 [桌面应用 | UWP 应用]
目标平台 Windows
标头 iphlpapi.h
Library Iphlpapi.lib
DLL Iphlpapi.dll

另请参阅

GetIpAddrTable

HeapAlloc

HeapFree

IP 帮助程序函数参考

IP 帮助程序起始页

IP_ADAPTER_ADDRESSES

MIB_IPADDRTABLE

SOCKET_ADDRESS

Windows 套接字