• MFC-GetAdaptersAddresses获取网卡信息


    需要:#pragma comment(lib, "IPHLPAPI.lib")

    GetAdaptersAddresses函数参数说明

    1. ULONG bufferSize = 0;
    2. ULONG result = ::GetAdaptersAddresses(AF_UNSPEC, GAA_FLAG_INCLUDE_PREFIX, nullptr, nullptr, &bufferSize);
    3. /*
    4. 参数1:ULONG Family 网络协议族,此参数须为下列值之一
    5. AF_UNSPEC=0 返回与启用了 IPv4 或 IPv6 的适配器关联的 IPv4 和 IPv6 地址
    6. AF_INET=2 仅返回与启用了 IPv4 的适配器关联的 IPv4 地址
    7. AF_INET6=23 仅返回与启用了 IPv6 的适配器关联的 IPv6 地址
    8. 参数2:ULONG Flags 要检索的地址类型
    9. 概念解释:
    10. 单播(Unicast):单播地址是一对一的通信方式,它用于将数据包从源地址发送到目标地址。
    11. 源地址指定发送者的唯一标识符,而目标地址指定接收者的唯一标识符。
    12. 只有目标地址与接收者匹配时,数据包才会传送给接收者。
    13. 广播(Broadcast):广播地址是一对多的通信方式,它用于将数据包发送给同一个网络中的所有设备。
    14. 广播地址是一个特殊的地址,用于指示所有设备都应该接收该数据包。
    15. 广播可以是有限的(局域网内)或无限的(所有网络都接收)。
    16. 多播(Multicast):多播地址是一对多的通信方式,它用于将数据包发送给一组特定的设备,这组设备被称为多播组。
    17. 多播地址也是一种特殊的地址,它表明数据包是按照多播方式进行传输的。只有加入该多播组的设备才会接收到数据包
    18. 此参数是以下值的组合。 如果此参数为零,则将返回单播、任意广播和多播 IP 地址
    19. GAA_FLAG_SKIP_UNICAST=0x0001 不要返回单播地址
    20. GAA_FLAG_SKIP_ANYCAST=0x0002 不要返回 IPv6 任何广播地址
    21. GAA_FLAG_SKIP_MULTICAST=0x0004 不要返回多播地址
    22. GAA_FLAG_SKIP_DNS_SERVER=0x0008 不要返回 DNS 服务器的地址
    23. GAA_FLAG_INCLUDE_PREFIX=0x0010 返回此适配器上的 IP 地址前缀列表。 设置此标志后,将返回 IPv6 和 IPv4 地址的 IP 地址前缀。
    24. GAA_FLAG_SKIP_FRIENDLY_NAME=0x0020 不要返回适配器友好名称
    25. GAA_FLAG_INCLUDE_WINS_INFO=0x0040 返回Windows Internet名称服务的地址 (WINS) 服务器。
    26. Windows Vista 及更高版本支持此标志
    27. GAA_FLAG_INCLUDE_GATEWAYS=0x0080 返回默认网关的地址,Windows Vista 及更高版本支持此标志
    28. GAA_FLAG_INCLUDE_ALL_INTERFACES=0x0100 返回所有NDIS接口的地址
    29. GAA_FLAG_INCLUDE_ALL_COMPARTMENTS=0x0200 返回所有路由隔离舱中的地址。此标志当前不受支持,并保留供将来使用
    30. GAA_FLAG_INCLUDE_TUNNEL_BINDINGORDER=0x0400 返回按隧道绑定顺序排序的适配器地址
    31. 参数3:PVOID Reserved 此参数当前未使用,但保留供将来系统使用。 调用应用程序应为此参数传递 NULL
    32. 参数4:[in, out] PIP_ADAPTER_ADDRESSES AdapterAddresses 指向缓冲区的指针,该缓冲区包含成功返回时 IP_ADAPTER_ADDRESSES 结构的链接列表
    33. 参数5:[in, out] PULONG SizePointer 指向变量的指针,该变量指定 AdapterAddresses 指向的缓冲区的大小
    34. 返回值:如果函数成功,则返回值 ERROR_SUCCESS=0 (定义为 与 NO_ERROR)
    35. 如果函数失败,则返回值为以下错误代码之一
    36. ERROR_ADDRESS_NOT_ASSOCIATED=1228 地址尚未与网络终结点关联。 DHCP 租约信息可用
    37. ERROR_BUFFER_OVERFLOW=111 SizePointer 参数指示的缓冲区大小太小,无法保存适配器信息或 AdapterAddresses 参数为 NULL
    38. ERROR_INVALID_PARAMETER=87 其中一个参数无效。
    39. 对于以下任一情况,将返回此错误: SizePointer 参数为 NULL、 Address 参数不 AF_INET、 AF_INET6或 AF_UNSPEC,
    40. 或者请求的参数的地址信息大于 ULONG_MAX。
    41. ERROR_NOT_ENOUGH_MEMORY=8 内存资源不足,无法完成操作
    42. ERROR_NO_DATA=232 找不到所请求参数的地址
    43. */

    GAA_FLAG_INCLUDE_PREFIX 什么是前缀列表 ?

    IP 适配器的前缀是指网络接口的 IP 地址所属的网段。例如,对于一个 IPv4 地址 192.168.1.100 和子网掩码 255.255.255.0,它的前缀就是 192.168.1.0/24。同一个网段内的所有网络设备可以通过 IP 地址进行互相通信,而不需要经过路由器

    IP_ADAPTER_ADDRESSES 结构体中常用字段的说明:

    1. Next: 指向下一个 IP_ADAPTER_ADDRESSES 结构体的指针。用于遍历多个网络适配器的链表。
    2. AdapterName: 网络适配器的名称,以字符串形式表示。
    3. Description: 网络适配器的描述信息,以字符串形式表示。
    4. FirstUnicastAddress: 指向一个 IP_ADAPTER_UNICAST_ADDRESS 结构体的指针,表示网卡的第一个单播地址(IPv4 或 IPv6)。
    5. FirstAnycastAddress: 指向一个 IP_ADAPTER_ANYCAST_ADDRESS 结构体的指针,表示网卡的第一个任播地址(IPv6)。
    6. FirstMulticastAddress: 指向一个 IP_ADAPTER_MULTICAST_ADDRESS 结构体的指针,表示网卡的第一个组播地址(IPv4 或 IPv6)。
    7. FirstDnsServerAddress: 指向一个 IP_ADAPTER_DNS_SERVER_ADDRESS 结构体的指针,表示网卡的第一个 DNS 服务器地址。
    8. DnsSuffix: DNS 后缀,以字符串形式表示。
    9. PWCHAR FriendlyName: 网络适配器的友好名称,以字符串形式表示。
    10. BYTE PhysicalAddress[MAX_ADAPTER_ADDRESS_LENGTH] : 网卡的物理地址(MAC 地址),以字节数组形式表示。
    11. ULONG PhysicalAddressLength: 物理地址的长度,以字节数表示
    12. IfIndex: 网络适配器的索引号。
    13. OperStatus: 网络适配器的操作状态,如 UP、DOWN 等。
    14. IfType: 网络适配器的类型,比如以太网、无线网卡等。
    15. Ipv6IfIndex: IPv6 协议的接口索引号。
    16. 这些字段提供了有关网络适配器的各种信息,如名称、描述、地址等。通过遍历 IP_ADAPTER_ADDRESSES 的链表,可以获取系统中所有的网络适配器的详细信息

    说明:

    PhysicalAddressLength

    PhysicalAddressLength 是指网卡的物理地址长度(或称为MAC地址长度)。在网络通信中,每个网卡都有一个唯一的物理地址,也称为MAC地址(Media Access Control Address)。

    物理地址是由48位(6个字节)的十六进制数字表示的,通常采用冒号或连字符来分隔每个字节。例如,物理地址的格式可以是 00:1A:2B:3C:4D:5E00-1A-2B-3C-4D-5E

    PhysicalAddressLength 变量表示物理地址的长度。在通常情况下,物理地址长度是固定的,为6个字节。因此,PhysicalAddressLength 的值通常是6。但是根据特定的网络设备或技术,也可能存在其他长度的物理地址。

    通过获取网卡的物理地址长度,我们可以在程序中为物理地址分配足够的内存空间,并确保正确解析和处理物理地址

    获取网卡的物理地址(MAC 地址)

    1. CString str;
    2. char buff[100];
    3. DWORD bufflen = 100;
    4. ULONG outBufLen = 0;
    5. ULONG dwRetVal = 0;
    6. PIP_ADAPTER_ADDRESSES pAddresses = nullptr;
    7. dwRetVal = ::GetAdaptersAddresses(AF_UNSPEC, 0, NULL, nullptr, &outBufLen);
    8. /*
    9. 第一次GetAdaptersAddresses,outBufLen=0,只是为了获取实际需要的大小
    10. */
    11. //pAddresses = (IP_ADAPTER_ADDRESSES*)malloc(outBufLen);
    12. //根据实际空间大小申请空间
    13. pAddresses = static_cast(malloc(outBufLen)); // 分配足够的缓冲区空间
    14. dwRetVal = ::GetAdaptersAddresses(AF_INET, GAA_FLAG_SKIP_ANYCAST, NULL, pAddresses, &outBufLen);
    15. /*
    16. AF_INET 仅返回与启用了 IPv4 的适配器关联的 IPv4 地址
    17. GAA_FLAG_SKIP_ANYCAST 不要返回 IPv6 任何广播地址
    18. */
    19. if (dwRetVal == NO_ERROR) {
    20. str.Format(_T("网络适配器的友好名称:%s \n"), pAddresses->FriendlyName);
    21. // 【以太网】
    22. str.Format(_T("物理地址的长度:%d \n"), pAddresses->PhysicalAddressLength);
    23. // 【6】
    24. int n = sizeof(pAddresses->PhysicalAddress) / sizeof(pAddresses->PhysicalAddress[0]); //网卡总数
    25. str.Format(_T("网卡总数:%d \n"), n);
    26. // 【8】
    27. for (int i = 0; i < n; i++) {
    28. str.Format(_T("网卡的物理地址(MAC 地址):n=%d %x \n"), i, pAddresses->PhysicalAddress[i]);
    29. ::OutputDebugString(str);
    30. /*
    31. 网卡的物理地址(MAC 地址):n=0 74
    32. 网卡的物理地址(MAC 地址):n=1 d0
    33. 网卡的物理地址(MAC 地址):n=2 2b
    34. 网卡的物理地址(MAC 地址):n=3 b7
    35. 网卡的物理地址(MAC 地址):n=4 3e
    36. 网卡的物理地址(MAC 地址):n=5 44
    37. 网卡的物理地址(MAC 地址):n=6 0
    38. 网卡的物理地址(MAC 地址):n=7 0
    39. */
    40. }
    41. }

  • 相关阅读:
    vs 自定义代码块 代码自动生成
    四级英语黄金词组及常用15个句型
    链表-算法总结
    Spring Security6 用户身份认证
    【阅读笔记】理解表驱动设计
    设计模式概念学习
    RocketMQ 基于时间轮算法实现指定时间点的定时消息原理解析
    牛客网刷题-(2)
    黑灰产套现城市消费券大揭秘
    【云原生】第十篇--Docker主机集群化方案 Docker Swarm
  • 原文地址:https://blog.csdn.net/lm68140318/article/details/132844254