getadaptersinfo是windows平台获取ipv4适配器基本信息的api,返回ip、子网掩码、网关、dns等,需两次调用(先获缓冲区大小再填充),仅支持ipv4且已弃用,推荐改用getadaptersaddresses。

Windows上用GetAdaptersInfo获取适配器基本信息
Windows平台最直接的方式是调用GetAdaptersInfo,它返回IPv4适配器的IP、子网掩码、网关、DNS等基础信息。注意这个API只支持IPv4,且已被标记为deprecated(但依然可用),适用于不需要IPv6或详细物理层信息的场景。
常见错误:忘记初始化pAdapterInfo指针或未检查ERROR_BUFFER_OVERFLOW导致崩溃;调用前没链接iphlpapi.lib会链接失败。
- 先调用一次
GetAdaptersInfo传入NULL和&dwBufLen,获取所需缓冲区大小 - 分配
BYTE*缓冲区(不是IP_ADAPTER_INFO*直接栈分配),再第二次调用 - 遍历链表时用
pAdapterInfo->Next,不是数组下标 - 记得释放缓冲区内存(
delete[] pAdapterInfo)
Windows推荐用GetAdaptersAddresses替代
GetAdaptersAddresses是GetAdaptersInfo的现代替代,支持IPv4/IPv6、物理地址(MAC)、接口索引、连接状态,并能过滤特定地址族。它更健壮,也更常用。
容易踩的坑:参数AF_UNSPEC会返回双栈信息,但数据量大;若只关心IPv4,显式传AF_INET可减少内存占用和解析开销。返回结构体IP_ADAPTER_ADDRESSES是链表,首节点可能为NULL(无适配器),需判空。
- 调用前确保
dwSize足够,同样需两轮调用(第一次获取size,第二次填充) -
FirstUnicastAddress字段指向该适配器所有IPv4/IPv6地址链表,需逐个遍历 -
PhysicalAddress长度由PhysicalAddressLength给出,不是固定6字节(某些虚拟网卡可能不同) - 记得用
FreeAdaptersAddresses释放内存,不能用delete[]
Linux/macOS用getifaddrs跨平台获取
getifaddrs是POSIX标准接口,在Linux和macOS上行为一致,返回包含所有协议族(AF_PACKET、AF_INET、AF_INET6等)的网络接口地址信息。它不提供MAC地址以外的高层配置(如DNS),但轻量、无需额外库。
典型问题:遍历链表时忘记检查ifa_next == nullptr导致越界;误把ifa_addr当字符串处理(它是sockaddr*,需根据sa_family类型cast);忽略AF_PACKET类型的接口(对应MAC层,ifa_addr为sockaddr_ll*)。
- 调用后必须用
freeifaddrs释放内存,否则内存泄漏 - 提取IPv4地址:判断
ifa_addr->sa_family == AF_INET,然后cast为sockaddr_in*,用inet_ntop转点分十进制 - 获取MAC地址:找
AF_PACKET节点,sockaddr_ll.sll_addr即为原始字节数组 - 接口名在
ifa_name字段,比如"eth0"或"en0"
跨平台封装要注意的细节
真正写跨平台代码时,别硬套同一套结构体——Windows的IP_ADAPTER_ADDRESSES和POSIX的ifaddrs字段语义差异大。建议抽象出最小公共集:接口名、IPv4地址、子网掩码、MAC地址(可选)、启用状态。
最容易被忽略的是权限和运行环境:Linux下读取某些接口信息(如UP状态、MAC)可能需要CAP_NET_RAW或root权限;macOS某些虚拟接口(如vEthernet)在非特权模式下可能不可见;Windows UWP沙箱环境则完全禁用这些API。
- 不要假设所有接口都有IPv4地址——有些只有IPv6或纯链路层
- “本地回环”接口(
lo/127.0.0.1)通常存在,但业务逻辑中常需过滤掉 - 虚拟机、Docker、WSL的网络接口命名和数量波动大,避免依赖固定名称(如硬编码
"eth0") - 获取到的MAC地址可能全零(如某些隧道接口),应做有效性校验
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











