我的任务是列出本地机器上的所有单播接口(通过网络掩码(IPv4(或前缀长度(IPv6(的IP地址和子网(。作为win32 API的新手,我正在阅读GetAdaptersAddress文档。有一个例子很清楚:
- 随着缓冲区大小的增加调用
GetAdaptersAddresses
,直到结果适合分配的内存块 - 迭代返回的PIP_ADAPTER_ADDRESSES(
pCurrAddresses
(链接列表:- 迭代PIP_ADAPTER_UNICAST_ADDRESS*
pCurrAddresses->FirstUnicastAddresses
链表以检索所有IP地址(SOCKET_ADDRESS及其LPSOCKADDRAddress->lpSockAddr
成员(;它是sockaddr_in*
或sockaddr_in6*
,取决于lpSockAddr.sa_family
(AF_INET
或AF_INET6
(
- 迭代PIP_ADAPTER_UNICAST_ADDRESS*
此时此刻,我有了IP地址。
网络掩码/前缀怎么样?这似乎就是PIP_ADAPTER_PREFIX_XP(及其SOCKET_ADDRESS Address
字段(的意义所在。这是另一个链表,可从PIP_ADAPTER_ADDRESSES
到->FirstPrefix
访问。
遗憾的是,文档指出前缀的排序可能与地址不同:
此外,链接的IP_ADAPTER_UNICAST_ADDRESS结构指向由FirstUnicastAddress成员和链接的FirstPrefix成员指向的IP_ADAPTER_PRIIX结构为由操作系统作为单独的内部链表进行维护。因此,链接的IP_ADAPTER_UNICAST_ADDRESS结构的顺序FirstUnicastAddress成员指向的没有与链接的IP_ADAPTER_PREFIX结构的顺序的关系由FirstPrefix成员指向。
解决方案是什么?我是不是错过了一些显而易见的东西?
某些代码(例如,zeroMQ(仅为每个适配器使用第一个单播地址和第一个前缀。这种方法安全吗?我会错过接口吗?
IP_ADAPTER_ADDRESSES::FirstPrefix
字段为您提供了分配给适配器的子网/前缀列表,但正如文档所述,GetAdaptersAddresses()
不会告诉您适配器上的哪个特定IP地址对应于哪个子网/后缀。因此,要确定每个IP地址的特定子网/前缀,您必须查看IP_ADAPTER_ADDRESSES::FirstUnicastAddresses
列表中的各个条目。
在Windows Vista及更高版本上,IP_ADAPTER_UNICAST_ADDRESS::OnLinkPrefixLength
字段为AF_INET
地址提供IPv4子网掩码的长度,为AF_INET6
地址提供IPv6前缀的长度。对于IPv4,如果需要实际的子网掩码,则可以将长度传递给ConvertLengthToIpv4Mask()
函数。
在Windows XP上,OnLinkPrefixLength
字段不存在。幸运的是,可以通过调用GetIpAddrTable()
函数,然后在表中查找IP地址(在MIB_IPADDRROW::dwAddr
字段中-子网掩码将在MIB_IPADDRROW::dwMask
字段中(来检索AF_INET
地址的IPv4子网掩码。
如果你需要的话,我不知道如何在XP上获得AF_INET6
地址的IPv6前缀长度。