需要:#pragma comment(lib, "IPHLPAPI.lib")
GetAdaptersAddresses函数参数说明
ULONG bufferSize = 0;ULONG result = ::GetAdaptersAddresses(AF_UNSPEC, GAA_FLAG_INCLUDE_PREFIX, nullptr, nullptr, &bufferSize);/*参数1:ULONG Family 网络协议族,此参数须为下列值之一AF_UNSPEC=0 返回与启用了 IPv4 或 IPv6 的适配器关联的 IPv4 和 IPv6 地址AF_INET=2 仅返回与启用了 IPv4 的适配器关联的 IPv4 地址AF_INET6=23 仅返回与启用了 IPv6 的适配器关联的 IPv6 地址参数2:ULONG Flags 要检索的地址类型概念解释:单播(Unicast):单播地址是一对一的通信方式,它用于将数据包从源地址发送到目标地址。源地址指定发送者的唯一标识符,而目标地址指定接收者的唯一标识符。只有目标地址与接收者匹配时,数据包才会传送给接收者。广播(Broadcast):广播地址是一对多的通信方式,它用于将数据包发送给同一个网络中的所有设备。广播地址是一个特殊的地址,用于指示所有设备都应该接收该数据包。广播可以是有限的(局域网内)或无限的(所有网络都接收)。多播(Multicast):多播地址是一对多的通信方式,它用于将数据包发送给一组特定的设备,这组设备被称为多播组。多播地址也是一种特殊的地址,它表明数据包是按照多播方式进行传输的。只有加入该多播组的设备才会接收到数据包此参数是以下值的组合。 如果此参数为零,则将返回单播、任意广播和多播 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 地址前缀。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接口的地址GAA_FLAG_INCLUDE_ALL_COMPARTMENTS=0x0200 返回所有路由隔离舱中的地址。此标志当前不受支持,并保留供将来使用GAA_FLAG_INCLUDE_TUNNEL_BINDINGORDER=0x0400 返回按隧道绑定顺序排序的适配器地址参数3:PVOID Reserved 此参数当前未使用,但保留供将来系统使用。 调用应用程序应为此参数传递 NULL参数4:[in, out] PIP_ADAPTER_ADDRESSES AdapterAddresses 指向缓冲区的指针,该缓冲区包含成功返回时 IP_ADAPTER_ADDRESSES 结构的链接列表参数5:[in, out] PULONG SizePointer 指向变量的指针,该变量指定 AdapterAddresses 指向的缓冲区的大小返回值:如果函数成功,则返回值 ERROR_SUCCESS=0 (定义为 与 NO_ERROR)如果函数失败,则返回值为以下错误代码之一ERROR_ADDRESS_NOT_ASSOCIATED=1228 地址尚未与网络终结点关联。 DHCP 租约信息可用ERROR_BUFFER_OVERFLOW=111 SizePointer 参数指示的缓冲区大小太小,无法保存适配器信息或 AdapterAddresses 参数为 NULLERROR_INVALID_PARAMETER=87 其中一个参数无效。对于以下任一情况,将返回此错误: SizePointer 参数为 NULL、 Address 参数不 AF_INET、 AF_INET6或 AF_UNSPEC,或者请求的参数的地址信息大于 ULONG_MAX。ERROR_NOT_ENOUGH_MEMORY=8 内存资源不足,无法完成操作ERROR_NO_DATA=232 找不到所请求参数的地址*/
GAA_FLAG_INCLUDE_PREFIX 什么是前缀列表 ?
IP 适配器的前缀是指网络接口的 IP 地址所属的网段。例如,对于一个 IPv4 地址 192.168.1.100
和子网掩码 255.255.255.0
,它的前缀就是 192.168.1.0/24
。同一个网段内的所有网络设备可以通过 IP 地址进行互相通信,而不需要经过路由器
IP_ADAPTER_ADDRESSES 结构体中常用字段的说明:
Next: 指向下一个 IP_ADAPTER_ADDRESSES 结构体的指针。用于遍历多个网络适配器的链表。AdapterName: 网络适配器的名称,以字符串形式表示。Description: 网络适配器的描述信息,以字符串形式表示。FirstUnicastAddress: 指向一个 IP_ADAPTER_UNICAST_ADDRESS 结构体的指针,表示网卡的第一个单播地址(IPv4 或 IPv6)。FirstAnycastAddress: 指向一个 IP_ADAPTER_ANYCAST_ADDRESS 结构体的指针,表示网卡的第一个任播地址(IPv6)。FirstMulticastAddress: 指向一个 IP_ADAPTER_MULTICAST_ADDRESS 结构体的指针,表示网卡的第一个组播地址(IPv4 或 IPv6)。FirstDnsServerAddress: 指向一个 IP_ADAPTER_DNS_SERVER_ADDRESS 结构体的指针,表示网卡的第一个 DNS 服务器地址。DnsSuffix: DNS 后缀,以字符串形式表示。PWCHAR FriendlyName: 网络适配器的友好名称,以字符串形式表示。BYTE PhysicalAddress[MAX_ADAPTER_ADDRESS_LENGTH] : 网卡的物理地址(MAC 地址),以字节数组形式表示。ULONG PhysicalAddressLength: 物理地址的长度,以字节数表示IfIndex: 网络适配器的索引号。OperStatus: 网络适配器的操作状态,如 UP、DOWN 等。IfType: 网络适配器的类型,比如以太网、无线网卡等。Ipv6IfIndex: IPv6 协议的接口索引号。这些字段提供了有关网络适配器的各种信息,如名称、描述、地址等。通过遍历 IP_ADAPTER_ADDRESSES 的链表,可以获取系统中所有的网络适配器的详细信息
说明:
PhysicalAddressLength
PhysicalAddressLength
是指网卡的物理地址长度(或称为MAC地址长度)。在网络通信中,每个网卡都有一个唯一的物理地址,也称为MAC地址(Media Access Control Address)。
物理地址是由48位(6个字节)的十六进制数字表示的,通常采用冒号或连字符来分隔每个字节。例如,物理地址的格式可以是 00:1A:2B:3C:4D:5E
或 00-1A-2B-3C-4D-5E
。
PhysicalAddressLength
变量表示物理地址的长度。在通常情况下,物理地址长度是固定的,为6个字节。因此,PhysicalAddressLength
的值通常是6。但是根据特定的网络设备或技术,也可能存在其他长度的物理地址。
通过获取网卡的物理地址长度,我们可以在程序中为物理地址分配足够的内存空间,并确保正确解析和处理物理地址
获取网卡的物理地址(MAC 地址)
CString str;char buff[100];DWORD bufflen = 100;ULONG outBufLen = 0;ULONG dwRetVal = 0;PIP_ADAPTER_ADDRESSES pAddresses = nullptr;dwRetVal = ::GetAdaptersAddresses(AF_UNSPEC, 0, NULL, nullptr, &outBufLen);/*第一次GetAdaptersAddresses,outBufLen=0,只是为了获取实际需要的大小*///pAddresses = (IP_ADAPTER_ADDRESSES*)malloc(outBufLen);//根据实际空间大小申请空间pAddresses = static_cast<IP_ADAPTER_ADDRESSES*>(malloc(outBufLen)); // 分配足够的缓冲区空间dwRetVal = ::GetAdaptersAddresses(AF_INET, GAA_FLAG_SKIP_ANYCAST, NULL, pAddresses, &outBufLen);/*AF_INET 仅返回与启用了 IPv4 的适配器关联的 IPv4 地址GAA_FLAG_SKIP_ANYCAST 不要返回 IPv6 任何广播地址*/if (dwRetVal == NO_ERROR) {str.Format(_T("网络适配器的友好名称:%s \n"), pAddresses->FriendlyName);// 【以太网】str.Format(_T("物理地址的长度:%d \n"), pAddresses->PhysicalAddressLength);// 【6】int n = sizeof(pAddresses->PhysicalAddress) / sizeof(pAddresses->PhysicalAddress[0]); //网卡总数str.Format(_T("网卡总数:%d \n"), n);// 【8】for (int i = 0; i < n; i++) {str.Format(_T("网卡的物理地址(MAC 地址):n=%d %x \n"), i, pAddresses->PhysicalAddress[i]);::OutputDebugString(str);/*网卡的物理地址(MAC 地址):n=0 74网卡的物理地址(MAC 地址):n=1 d0网卡的物理地址(MAC 地址):n=2 2b网卡的物理地址(MAC 地址):n=3 b7网卡的物理地址(MAC 地址):n=4 3e网卡的物理地址(MAC 地址):n=5 44网卡的物理地址(MAC 地址):n=6 0网卡的物理地址(MAC 地址):n=7 0*/}}