About
The style environment of this article: win10 + vs2017 + c++11
1.Description
It’s a trap. I always thought that a network card can only have one IP. Today I found that in the structure, the relevant structure is defined: One network card can use Multiple IPs.
2. Connection library and header file
- 2.1 Header files
#include <WinSock2.h> #include <Iphlpapi.h>
- 2.2 Library
Iphlpapi.lib
3. Encapsulation class
I made a package myself and just use it later.
- 3.1 Header file source code
#pragma once #include <string> #include <list> #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 \t #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() { #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: //------------------------------------------------ ---------------------------------------- \t\t static net_adapter_helper & amp; get_instance(); /** * @brief: Get Windows network card information */ net_ada_list get_info_win(); private: template<typename ... Args> static std::string str_format(const std::string & amp;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 Source file source code
#include "ip_helper.h" #include#include #if defined(os_is_win) #include <WinSock2.h> #include <Iphlpapi.h> #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< IP_ADAPTER_INFO> 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. Call the GetAdaptersInfo function and fill in the pIpAdapterInfo pointer variable; where the stSize parameter is both an input quantity and an output quantity. int ret_val = GetAdaptersInfo(pai.get(), & amp;iai_size); if (ERROR_BUFFER_OVERFLOW == ret_val) { pai.release(); //Reapply for memory space to store all network card information pai.reset((IP_ADAPTER_INFO*)(new(std::nothrow) char[iai_size])); if (nullptr == pai || NULL == pai) { return ret_list; } //Call the GetAdaptersInfo function again to fill in the pIpAdapterInfo pointer variable 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->Index; item._name = std::string(ppai->AdapterName); item._description = std::string(ppai->Description); // dev std::string str_type; switch (ppai->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 < ppai->AddressLength; i + + ) { if (i < ppai->AddressLength - 1) str_mac + = str_format(" X-", ppai->Address[i]); else str_mac + = str_format(" X", ppai->Address[i]); } item._mac = str_mac; // IP information ip_info ii_item; IP_ADDR_STRING *pial = & amp;(ppai->IpAddressList); int ip_size = 0; for (;;) { if (NULL != pial & amp; & amp; nullptr != pial) { ii_item._inet4 = std::string(pial->IpAddress.String); ii_item._subnet_mask = std::string(pial->IpMask.String); ii_item._gate = std::string(pai->GatewayList.IpAddress.String); item._ip.push_back(ii_item); pial = pial->Next; ii_item.zero(); ip_size + + ; } else { break; } } item._ip_size = ip_size; ret_list.push_back(item); item.zero(); ppai = ppai->Next; } // end while } else { ;// error } return ret_list; } }
4.Use
net_ada_list nal = net_adapter_helper::get_instance().get_info_win(); int list_size = nal.size(); cout << "1.Number of adapters = " << list_size << "\ \ " << endl; #if defined(os_is_win) for (auto item : nal) { cout << "index=" << item._index << endl; cout << "name=" << item._name.c_str() << endl; cout << "Description=" << item._description.c_str() << endl; cout << "type=" << item._dev_type.c_str() << endl; cout << "MAC=" << item._mac.c_str() << endl; int index = 0; cout << "ip has=" << item._ip_size << "pieces" << endl; for (auto item_ip : item._ip) { cout << "th" << + + index << "ip" << endl; cout << "ipv4 = " << item_ip._inet4.c_str() << endl; cout << "Subnet mask = " << item_ip._subnet_mask.c_str() << endl; cout << "Gateway = " << item_ip._gate.c_str() << endl; cout << "\ -------------------------"; } cout << "\ -------------------------------------------------- ------\ \ "; } #endif //