C++使用GetAdaptersInfo获取本机MAC、IP及子网掩码

宋时安
宋时安
发布时间:2026-10-14 | 4人浏览过
原创

在C++ Windows程序开发中,获取本机的网络配置信息(如MAC地址、IP和子网掩码)通常需要调用Win32 API。本文将通过具体代码示例,演示如何利用 iphlpapi.h 中的 GetAdaptersInfo 接口完成这一任务,并处理相关的内存管理。

实现原理与准备

获取网络适配器信息主要依赖Windows提供的 IP Helper API。该方法的核心流程分为三步:首先通过两次调用确定所需缓冲区的大小;其次分配内存并再次调用以填充结构体;最后从 IP_ADAPTER_INFO 结构体中提取所需的网络参数。 需要注意的是,该API仅返回第一个网络适配器的信息(即默认路由接口),对于多网卡环境可能需要遍历列表,但本示例聚焦于基础功能的实现。

代码实现步骤

第1步:引入必要头文件与链接库

为了使用网络相关函数,必须包含 iphlpapi.h 并链接对应的静态库 IPHLPAPI.lib。同时,由于涉及Socket初始化,通常也需要基础的Socket头文件支持。

#include <stdio.h>
#include <iphlpapi.h>
#pragma comment(lib, "IPHLPAPI.lib")
// 假设存在自定义的Socket初始化类
#include "InitSock.h" 

第2步:定义全局变量用于存储结果

为方便演示,我们在函数外部定义全局变量来接收获取到的MAC地址(6字节)、网关IP、本地IP和子网掩码。

u_char g_ucLocalMac[6];
DWORD g_dwGatewayIP;
DWORD g_dwLocalIP;
DWORD g_dwMask;

第3步:获取并解析适配器信息

创建 GetGlobalData 函数执行核心逻辑。使用 GetAdaptersInfo 时,初始调用传入NULL指针和0大小,函数会返回实际需要的缓冲区大小。随后使用 GlobalAlloc 分配内存并再次调用获取真实数据。

BOOL GetGlobalData()
{
    PIP_ADAPTER_INFO pAdapterInfo = NULL;
    ULONG ulSize = 0;
    
    // 第一次调用:获取所需缓冲区大小
    ::GetAdaptersInfo(pAdapterInfo, &ulSize);
    
    // 分配内存
    pAdapterInfo = (PIP_ADAPTER_INFO)::GlobalAlloc(GPTR, ulSize);
    
    // 第二次调用:获取实际数据
    if (ERROR_SUCCESS == ::GetAdaptersInfo(pAdapterInfo, &ulSize))
    {
        if (pAdapterInfo != NULL)
        {
            // 提取MAC地址(前6字节)
            memcpy(g_ucLocalMac, pAdapterInfo->Address, 6);
            
            // 提取网关IP(转换为主机字节序)
            g_dwGatewayIP = ::inet_addr(pAdapterInfo->GatewayList.IpAddress.String);
            
            // 提取本地IP
            g_dwLocalIP = ::inet_addr(pAdapterInfo->IpAddressList.IpAddress.String);
            
            // 提取子网掩码
            g_dwMask = ::inet_addr(pAdapterInfo->IpAddressList.IpMask.String);
        }
    }
    
    // 打印输出格式化处理
    in_addr in;
    
    in.S_un.S_addr = g_dwLocalIP;
    printf(" IP Address:%-30s\n", ::inet_ntoa(in));

    in.S_un.S_addr = g_dwGatewayIP;
    printf(" Gateway Address:%-30s\n", ::inet_ntoa(in));

    in.S_un.S_addr = g_dwMask;
    printf(" MASK Address:%-30s\n", ::inet_ntoa(in));

    u_char* p = g_ucLocalMac;
    printf(" MAC:%02X-%02X-%02X-%02X-%02X-%02X\n", p[0], p[1], p[2], p[3], p[4], p[5]);
    
    // 释放内存
    ::GlobalFree(pAdapterInfo);
    pAdapterInfo = NULL;
    return TRUE;
}

第4步:主函数调用与环境初始化

在 main 函数中,首先需要初始化WinSock(确保网络栈可用),然后调用上述获取函数。

void main()
{
    CInitSock initSock; // 假设此类负责WSAStartup
    
    GetGlobalData();
    
    printf("*******************************");
    getchar(); // 暂停以便观察输出
}

注意事项与排查

  • 权限问题:在较新的Windows版本中,部分高级网络信息可能受UAC限制,普通管理员权限通常足够,但某些虚拟网卡可能无法读取准确的MAC地址。
  • 内存泄漏风险:示例中使用 GlobalAlloc 必须在获取成功后或异常时通过 GlobalFree 释放,否则会导致内存泄漏。现代C++建议使用 std::unique_ptr 或智能指针进行更安全的资源管理。
  • IPv6支持:GetAdaptersInfo 仅支持IPv4。若需获取IPv6地址或处理多网卡完整列表,应改用 GetAdaptersAddresses 函数。

总结

通过 iphlpapi.h 提供的接口,开发者可以便捷地在C++应用中获取本机基本网络标识。理解缓冲区的两次调用模式是避免崩溃的关键。以上就是利用C++获取本机MAC、IP及MASK地址的详细内容,更多关于C++网络编程的资料请关注本站其它相关文章!

相关标签:

本站声明

本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。

Python 相关产品和应用

全部下载

专题列表