Windows10 c++获取网卡信息(ipv4,子网掩码,网关,mac地址)
阅读原文时间:2023年07月09日阅读:2

本文样式环境: win10 + vs2017 + c++11

算是踩坑吧,先前一直认为一块网卡只能有一个IP。 今天发现结构体中,定义了相关结构: 一块网卡可以用多个IP

  • 2.1 头文件

    #include
    #include

  • 2.2 库

    Iphlpapi.lib

自己做了个封装,以后用,直接就它了。

  • 3.1 头文件 源码

    #pragma once
    #include
    #include

    #if defined(_WIN32) || defined(_WIN64)
    #ifndef os_is_win
    #define os_is_win
    #endif // !os_is_win

    #elif defined(linux) || defined(linux) || defined(_unix) || defined(_unix) || defined(APPLE)
    #ifndef os_is_linux
    #define os_is_linux
    #endif // !os_is_linux

    #endif// ! defined(_WIN32) || defined(_WIN64)

    #if defined(os_is_win)

    #ifndef _net_api_export_
        #define _net_api_export_ __declspec(dllexport)
    #else
        #define _net_api_export_ __declspec(dllimport)
    #endif // !#ifndef  _net_api_export_

    #elif defined(os_is_linux)

    #ifndef _net_api_export_
        #define _net_api_export_  __attribute__((visibility ("default")))
    #endif // !_net_api_export_

    #endif //! defined(os_is_win)

    namespace lib_net
    {

    /**
    * @brief: ip information
    */
    struct ip_info_
    {
        std::string _inet4;
        std::string _inet6;
        std::string _subnet_mask;
        std::string _gate;
    void zero()
    {
        _inet4          = { "" };
        _inet6          = { "" };
        _subnet_mask    = { "" };
        _gate           = { "" };
    }
    
    ip_info_()
    {
        zero();
    }
    }; using ip_info = ip_info_; using ip_list = std::list< ip_info>; /** * @brief: the information of adapter */ struct net_adapter_info_ {

    #ifdef os_is_win
    int _index;
    #endif //! os_is_win

        std::string _name;
        std::string _description;
        std::string _dev_type;
        std::string _mac;
    ip_list     _ip;
    int         _ip_size;
    
    void zero()
    {</code></pre>

    #ifdef os_is_win
    _index = 0;
    #endif //! os_is_win
    _name = { "" };
    _description = { "" };
    _dev_type = { "" };
    _mac = { "" };
    _ip.clear();
    _ip_size = 0;
    }

        net_adapter_info_()
        {
            zero();
        }
    };
    
    // to rename the type
    using net_ada_info = net_adapter_info_;
    
    // maybe, this machine has greater than 1 adapter
    using net_ada_list = std::list<net_ada_info>;

    //----------------------------------------------------------------------------------------

    /**
    * @brief: you could get the adapter information through this class on windows, linux and osx
    */
    class _net_api_export_ net_adapter_helper
    {
    public:
    //----------------------------------------------------------------------------------------
    static net_adapter_helper&amp; get_instance();
    
    /**
    * @brief: 获取Windows网卡信息
    */
    net_ada_list get_info_win();
    private: template<typename ... Args> static std::string str_format(const std::string &format, Args ... args) { auto size_buf = std::snprintf(nullptr, 0, format.c_str(), args ...) + 1; std::unique_ptr<char[]> buf(new(std::nothrow) char[size_buf]);
        if (!buf)
            return std::string("");
    
        std::snprintf(buf.get(), size_buf, format.c_str(), args ...);
    
        return std::string(buf.get(), buf.get() + size_buf - 1);
    }
    //---------------------------------------------------------------------------------------- net_adapter_helper() = default; virtual ~net_adapter_helper() = default;
    net_adapter_helper(const net_adapter_helper&amp; instance) = delete;
    net_adapter_helper&amp; operator = (const net_adapter_helper&amp; instance) = delete;
    net_adapter_helper(const net_adapter_helper&amp;&amp; instance) = delete;
    net_adapter_helper&amp; operator = (const net_adapter_helper&amp;&amp; instance) = delete;
    };

    }

  • 3.2 源文件源码

    #include "ip_helper.h"

    #include
    #include

    #if defined(os_is_win)
    #include
    #include
    #endif //! defined(os_is_win)

    namespace lib_net
    {

    /**
    *   @brief:
    */
    lib_net::net_adapter_helper& net_adapter_helper::get_instance()
    {
        static net_adapter_helper instance;
    return instance;
    } /** * @brief: */ lib_net::net_ada_list net_adapter_helper::get_info_win() { net_ada_list ret_list;
    std::unique_ptr&lt; IP_ADAPTER_INFO&gt; pai(new(std::nothrow) IP_ADAPTER_INFO);
    
    // 1. failed to apply space
    if (nullptr == pai || NULL == pai)
        return ret_list;
    
    // 2. to get the size of IP_ADAPTER_INFO structure
    unsigned long iai_size = sizeof(IP_ADAPTER_INFO);
    
    // 3.调用GetAdaptersInfo函数, 填充pIpAdapterInfo指针变量; 其中stSize参数既是一个输入量也是一个输出量
    int ret_val = GetAdaptersInfo(pai.get(), &amp;iai_size);
    
    if (ERROR_BUFFER_OVERFLOW == ret_val)
    {
        pai.release();
    
        //重新申请内存空间用来存储所有网卡信息
        pai.reset((IP_ADAPTER_INFO*)(new(std::nothrow) char[iai_size]));
    
        if (nullptr == pai || NULL == pai)
        {
            return ret_list;
        }
    
        //再次调用GetAdaptersInfo函数,填充pIpAdapterInfo指针变量
        ret_val = GetAdaptersInfo(pai.get(), &amp;iai_size);
    }
    
    if (ERROR_SUCCESS == ret_val)
    {
        // 3. to get information
        net_ada_info item;
        IP_ADAPTER_INFO *ppai = pai.get();
    
        while (ppai)
        {
            item._index         = ppai-&gt;Index;
            item._name          = std::string(ppai-&gt;AdapterName);
            item._description   = std::string(ppai-&gt;Description);
    
            // dev
            std::string str_type;
            switch (ppai-&gt;Type)
            {
            case MIB_IF_TYPE_OTHER:
                str_type = {"OTHER"};
                break;
    
            case MIB_IF_TYPE_ETHERNET:
                str_type = { "ETHERNET" };
                break;
    
            case MIB_IF_TYPE_TOKENRING:
                str_type = { "TOKENRING" };
                break;
    
            case MIB_IF_TYPE_FDDI:
                str_type = { "FDDI" };
                break;
    
            case MIB_IF_TYPE_PPP:
                str_type = { "PPP" };
                break;
    
            case MIB_IF_TYPE_LOOPBACK:
                str_type = { "LOOPBACK" };
                break;
    
            case MIB_IF_TYPE_SLIP:
                str_type = { "SLP" };
                break;
    
            default:
                str_type = { "" };
                break;
            }
    
            item._dev_type = str_type;
    
            // mac
            std::string str_mac;
            for (DWORD i = 0; i &lt; ppai-&gt;AddressLength; i++)
            {
                if (i &lt; ppai-&gt;AddressLength - 1)
                    str_mac += str_format("%02X-", ppai-&gt;Address[i]);
                else
                    str_mac += str_format("%02X", ppai-&gt;Address[i]);
            }
    
            item._mac = str_mac;
    
            // ip information
            ip_info ii_item;
            IP_ADDR_STRING *pial            = &amp;(ppai-&gt;IpAddressList);
            int ip_size                     = 0;
            for (;;)
            {
                if (NULL != pial &amp;&amp; nullptr != pial)
                {
                    ii_item._inet4          = std::string(pial-&gt;IpAddress.String);
                    ii_item._subnet_mask    = std::string(pial-&gt;IpMask.String);
                    ii_item._gate           = std::string(pai-&gt;GatewayList.IpAddress.String);
    
                    item._ip.push_back(ii_item);
                    pial                    = pial-&gt;Next;
                    ii_item.zero();
                    ip_size++;
                }
                else
                {
                    break;
                }
            } 
    
            item._ip_size   = ip_size;
            ret_list.push_back(item);
            item.zero();
    
            ppai = ppai-&gt;Next;
        } // end while
    }
    else
    {
        ;// error
    }
    
    return ret_list;
    }

    }

    net_ada_list nal = net_adapter_helper::get_instance().get_info_win();
    int list_size = nal.size();

    cout << "1.适配器数目 = " << list_size << "\n\n" << endl;

    #if defined(os_is_win)
    for (auto item : nal)
    {
    cout << "索引=" << item._index << endl;
    cout << "名字=" << item._name.c_str() << endl;
    cout << "描述=" << item._description.c_str() << endl;
    cout << "类型=" << item._dev_type.c_str() << endl;
    cout << "MAC=" << item._mac.c_str() << endl;

    int index = 0;
    cout << "ip有=" << item._ip_size << "个" << endl;
    for (auto item_ip : item._ip)
    {
        cout << "第" << ++index << "个ip" << endl;
        cout << "ipv4 = " << item_ip._inet4.c_str() << endl;
        cout << "子网掩码 = " << item_ip._subnet_mask.c_str() << endl;
        cout << "网关 = " << item_ip._gate.c_str() << endl;
        cout << "\n-------------------------";
    }
    
    cout << "\n--------------------------------------------------\n\n";

    }

    #endif //

手机扫一扫

移动阅读更方便

阿里云服务器
腾讯云服务器
七牛云服务器

你可能感兴趣的文章