Windows下获取网卡基础信息及MAC地址IP子网掩码DNS信息

xingyun86 2021-4-16 1451

Windows下获取网卡基础信息及MAC地址IP子网掩码DNS信息

#pragma once

#include <winsock2.h>
#pragma comment(lib,"ws2_32.lib")
#include <ws2tcpip.h>
#include <tcpestats.h>
#include <iphlpapi.h>
#pragma comment(lib,"iphlpapi.lib")
#include <vector>
#include <unordered_map>
#include <utils.h>

class CNetworkMgr {
public:

#if (_WIN32_WINNT < 0x0600/*_WIN32_WINNT_VISTA*/)

#define IN6ADDRSZ 16 
#define    INT16SZ         2

    static const char* inet_ntop4(const u_char* src, char* dst, size_t size)
    {
        static const char fmt[] = "%u.%u.%u.%u";
        char tmp[sizeof "255.255.255.255"];

        sprintf(tmp, fmt, src[0], src[1], src[2], src[3]);
        if (strlen(tmp) > size) {
            return NULL;
        }
        strcpy(dst, tmp);
        return (dst);
    }

    static const char* inet_ntop6(const u_char* src, char* dst, size_t size)
    {
        /*
         * Note that int32_t and int16_t need only be "at least" large enough
         * to contain a value of the specified size.  On some systems, like
         * Crays, there is no such thing as an integer variable with 16 bits.
         * Keep this in mind if you think this function should have been coded
         * to use pointer overlays.  All the world's not a VAX.
         */
        char tmp[sizeof "ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255"], * tp;
        struct { int base, len; } best, cur;
        u_int words[IN6ADDRSZ / INT16SZ];
        int i;

        /*
         * Preprocess:
         *    Copy the input (bytewise) array into a wordwise array.
         *    Find the longest run of 0x00's in src[] for :: shorthanding.
         */
        memset(words, 0, sizeof words);
        for (i = 0; i < IN6ADDRSZ; i++)
            words[i / 2] |= (src[i] << ((1 - (i % 2)) << 3));
        best.base = -1;
        cur.base = -1;
        for (i = 0; i < (IN6ADDRSZ / INT16SZ); i++) {
            if (words[i] == 0) {
                if (cur.base == -1)
                    cur.base = i, cur.len = 1;
                else
                    cur.len++;
            }
            else {
                if (cur.base != -1) {
                    if (best.base == -1 || cur.len > best.len)
                        best = cur;
                    cur.base = -1;
                }
            }
        }
        if (cur.base != -1) {
            if (best.base == -1 || cur.len > best.len)
                best = cur;
        }
        if (best.base != -1 && best.len < 2)
            best.base = -1;

        /*
         * Format the result.
         */
        tp = tmp;
        for (i = 0; i < (IN6ADDRSZ / INT16SZ); i++) {
            /* Are we inside the best run of 0x00's? */
            if (best.base != -1 && i >= best.base &&
                i < (best.base + best.len)) {
                if (i == best.base)
                    *tp++ = ':';
                continue;
            }
            /* Are we following an initial run of 0x00s or any real hex? */
            if (i != 0)
                *tp++ = ':';
            /* Is this address an encapsulated IPv4? */
            if (i == 6 && best.base == 0 &&
                (best.len == 6 || (best.len == 5 && words[5] == 0xffff))) {
                if (!inet_ntop4(src + 12, tp, sizeof tmp - (tp - tmp)))
                    return (NULL);
                tp += strlen(tp);
                break;
            }
            sprintf(tp, "%x", words[i]);
            tp += strlen(tp);
        }
        /* Was it a trailing run of 0x00's? */
        if (best.base != -1 && (best.base + best.len) == (IN6ADDRSZ / INT16SZ))
            *tp++ = ':';
        *tp++ = '\0';

        /*
         * Check for overflow, copy, and we're done.
         */
        if ((tp - tmp) > size) {
            return (NULL);
        }
        strcpy(dst, tmp);
        return (dst);
    }

    static const char* inet_ntop(int af, const void* src, char* dst, size_t size)
    {
        switch (af) {
        case AF_INET:
            return (inet_ntop4((const u_char*)src, dst, size));
        case AF_INET6:
            return (inet_ntop6((const u_char*)src, dst, size));
        default:
            return (NULL);
        }
        /* NOTREACHED */
    }
#endif//(0x0600/*_WIN32_WINNT_VISTA*/)

    class InOutBytes {
    public:
        uint64_t InBytes = 0;
        uint64_t OutBytes = 0;
        void clear()
        {
            this->InBytes = 0;
            this->OutBytes = 0;
        }
    };
    class NICInfo
    {
    public:
        std::string FriendlyName = ("");        //显示名称
        std::string AdapterName = ("");            //网卡名称
        std::string Description = ("");            //网卡描述
        std::string MacAddr = ("");                //MAC地址
        std::string CurrentIpAddress = ("");    //当前IP地址
        std::unordered_map<std::string, std::string> IpAddressMaskList = {};  //<IP地址,子网掩码>列表
        std::vector<std::string> GateAwayIpAddressList = {};  //网关IP地址列表
        std::vector<std::string> DNSIpAddressList = {};    //DNS列表
        InOutBytes BytesLinkSpeed = {};//接收和发送带宽速率
    };
    std::vector<NICInfo> m_nicInfoList = {};
    InOutBytes m_totalBytes = {};
    InOutBytes m_totalBytesPerSecond = {};
    std::unordered_map<DWORD, InOutBytes> m_procStatList = {};
    std::unordered_map<DWORD, InOutBytes> m_procStatSpeedList = {};

    BOOL GetHostAdaptersInfo()     //获取网卡信息 及 IP地址 列表
    {
        m_nicInfoList.clear();

        ULONG ulRet = 0;
        PBYTE pIpAdapterInfo = NULL;
        ULONG ulAdapterInfoSize = 0;
        ULONG Flags = GAA_FLAG_INCLUDE_PREFIX | GAA_FLAG_INCLUDE_GATEWAYS;//包括 IPV4 ,IPV6 网关
        ULONG Family = AF_INET;// AF_UNSPEC;//返回包括 IPV4 和 IPV6 地址
        PBYTE pIpAdapterAddresses = NULL;
        ULONG ulAdapterAddressSize = 0;
        PIP_ADAPTER_INFO pAdapterInfoIterater = NULL;
        PIP_ADAPTER_ADDRESSES pAdapterAddressIterater = NULL;
        IP_ADAPTER_DNS_SERVER_ADDRESS* pIpAdapterDNSServerAddress = NULL;
        ulRet = GetAdaptersAddresses(Family, Flags, NULL, (PIP_ADAPTER_ADDRESSES)pIpAdapterAddresses, &ulAdapterAddressSize);
        if (ulRet == ERROR_BUFFER_OVERFLOW)
        {
            //重新分配大小
            pIpAdapterAddresses = new BYTE[ulAdapterAddressSize];
            if (pIpAdapterAddresses == nullptr)
            {
                return FALSE;
            }

            //获取适配器信息
            ulRet = GetAdaptersAddresses(Family, Flags, NULL, (PIP_ADAPTER_ADDRESSES)pIpAdapterAddresses, &ulAdapterAddressSize);
            //获取失败
            if (ulRet != ERROR_SUCCESS)
            {
                if (pIpAdapterAddresses != nullptr)
                {
                    delete[]pIpAdapterAddresses;
                }
                return FALSE;
            }
            pAdapterAddressIterater = (PIP_ADAPTER_ADDRESSES)pIpAdapterAddresses;
        }

        //获取适配器信息
        ulRet = GetAdaptersInfo((PIP_ADAPTER_INFO)pIpAdapterInfo, &ulAdapterInfoSize);
        if (ulRet == ERROR_BUFFER_OVERFLOW)
        {
            //重新分配大小
            pIpAdapterInfo = new BYTE[ulAdapterInfoSize];
            if (pIpAdapterInfo == nullptr)
            {
                if (pIpAdapterAddresses != nullptr)
                {
                    delete[]pIpAdapterAddresses;
                }
                return FALSE;
            }

            //获取适配器信息
            ulRet = GetAdaptersInfo((PIP_ADAPTER_INFO)pIpAdapterInfo, &ulAdapterInfoSize);

            //获取失败
            if (ulRet != ERROR_SUCCESS)
            {
                if (pIpAdapterAddresses != nullptr)
                {
                    delete[]pIpAdapterAddresses;
                }
                if (pIpAdapterInfo != NULL)
                {
                    delete[]pIpAdapterInfo;
                }
                return FALSE;
            }
            pAdapterInfoIterater = (PIP_ADAPTER_INFO)pIpAdapterInfo;
        }

        while (pAdapterInfoIterater != nullptr)
        {
            NICInfo nicInfo = { };
            nicInfo.AdapterName = pAdapterInfoIterater->AdapterName;   //网卡名称
            nicInfo.Description = pAdapterInfoIterater->Description;   //网卡描述

            //MAC地址
            nicInfo.MacAddr = CUtils::format_string("%02X-%02X-%02X-%02X-%02X-%02X",
                pAdapterInfoIterater->Address[0], pAdapterInfoIterater->Address[1], pAdapterInfoIterater->Address[2],
                pAdapterInfoIterater->Address[3], pAdapterInfoIterater->Address[4], pAdapterInfoIterater->Address[5]);
            //当前IP地址
            if (pAdapterInfoIterater->CurrentIpAddress != nullptr)
            {
                nicInfo.CurrentIpAddress = pAdapterInfoIterater->CurrentIpAddress->IpAddress.String;
            }
            //指向IP地址子网掩码列表
            PIP_ADDR_STRING pIpAddr = &pAdapterInfoIterater->IpAddressList;
            while (pIpAddr != nullptr)
            {
                nicInfo.IpAddressMaskList.emplace(pIpAddr->IpAddress.String, pIpAddr->IpMask.String);//<IP地址,子网掩码>
                //指向网关地址列表
                PIP_ADDR_STRING pGateAwayList = &pAdapterInfoIterater->GatewayList;
                while (pGateAwayList != nullptr)
                {
                    nicInfo.GateAwayIpAddressList.emplace_back(pGateAwayList->IpAddress.String);   //网关    
                    pGateAwayList = pGateAwayList->Next;
                }

                pIpAddr = pIpAddr->Next;
            }
            //DNS1/DNS2地址
            pAdapterAddressIterater = (PIP_ADAPTER_ADDRESSES)pIpAdapterAddresses;
            while (pAdapterAddressIterater != nullptr)
            {
                if (nicInfo.AdapterName.compare(pAdapterAddressIterater->AdapterName) == 0)
                {
                    nicInfo.FriendlyName = CUtils::W_To_A(pAdapterAddressIterater->FriendlyName);
                    nicInfo.BytesLinkSpeed.InBytes = pAdapterAddressIterater->ReceiveLinkSpeed;
                    nicInfo.BytesLinkSpeed.OutBytes = pAdapterAddressIterater->TransmitLinkSpeed;
                    pIpAdapterDNSServerAddress = pAdapterAddressIterater->FirstDnsServerAddress;
                    while (pIpAdapterDNSServerAddress != nullptr)
                    {
                        CHAR DNS[132] = { 0 };
                        switch (pIpAdapterDNSServerAddress->Address.lpSockaddr->sa_family)
                        {
                        case AF_INET:
                        {
                            inet_ntop(pIpAdapterDNSServerAddress->Address.lpSockaddr->sa_family, &((sockaddr_in*)pIpAdapterDNSServerAddress->Address.lpSockaddr)->sin_addr, DNS, sizeof(DNS));
                            nicInfo.DNSIpAddressList.emplace_back(DNS);
                        }
                        break;
                        case AF_INET6:
                        {
                            inet_ntop(pIpAdapterDNSServerAddress->Address.lpSockaddr->sa_family, &((sockaddr_in6*)pIpAdapterDNSServerAddress->Address.lpSockaddr)->sin6_addr, DNS, sizeof(DNS));
                        }
                        break;
                        default:
                            break;
                        }
                        pIpAdapterDNSServerAddress = pIpAdapterDNSServerAddress->Next;
                    }
                    break;
                }
                pAdapterAddressIterater = pAdapterAddressIterater->Next;
            }
            m_nicInfoList.emplace_back(nicInfo);

            pAdapterInfoIterater = pAdapterInfoIterater->Next;
        }
        
        if (pIpAdapterInfo != nullptr)
        {
            delete[]pIpAdapterInfo;
        }

        if (pIpAdapterAddresses != nullptr)
        {
            delete[]pIpAdapterAddresses;
        }

        return TRUE;
    }
    void GetProcessIpInOutBytes()
    {
        GetNetworkProcessStat(m_procStatList);
    }
    void GetProcessIpInOutSpeed()
    {
        std::unordered_map<DWORD, InOutBytes> procStatSpeedList = {};
        m_procStatSpeedList.clear();

        GetNetworkProcessStat(procStatSpeedList);
        TIMERSTARTS(A);
        std::this_thread::sleep_for(std::chrono::milliseconds(1000));
        GetNetworkProcessStat(m_procStatSpeedList);
        TIMERSTARTS(B);

        for (auto &it : m_procStatSpeedList)
        {
            auto itFind = procStatSpeedList.find(it.first);
            if(itFind != procStatSpeedList.end())
            {
                it.second.InBytes = (it.second.InBytes - itFind->second.InBytes) * 1000 / TIMERCNT_MS(A, B);
                it.second.OutBytes = (it.second.OutBytes - itFind->second.OutBytes) * 1000 / TIMERCNT_MS(A, B);
            }
        }
    }
    void GetIpInOutBytes()
    {
        m_totalBytes.clear();
        GetTotalIpStatistics(m_totalBytes);
    }
    void GetIpInOutSpeed()
    {
        InOutBytes utotalBytesPerSecond = {};
        m_totalBytesPerSecond.clear();

        GetTotalIpStatistics(utotalBytesPerSecond);
        TIMERSTARTS(A);
        std::this_thread::sleep_for(std::chrono::milliseconds(1000));
        GetTotalIpStatistics(m_totalBytesPerSecond);
        TIMERSTARTS(B);
        m_totalBytesPerSecond.InBytes = (m_totalBytesPerSecond.InBytes - utotalBytesPerSecond.InBytes) * 1000 / TIMERCNT_MS(A, B);
        m_totalBytesPerSecond.OutBytes = (m_totalBytesPerSecond.OutBytes - utotalBytesPerSecond.OutBytes) * 1000 / TIMERCNT_MS(A, B);
    }
    double ToK(uint64_t n) { return (double)n / 1024; }
    double ToM(uint64_t n) { return (double)n / 1024 / 1024; }
    double ToG(uint64_t n) { return (double)n / 1024 / 1024 / 1024; }
    std::string ToKMG(uint64_t n)
    {
        if (n > 1024)
        {
            if ((n / 1024) > 1024)
            {
                if ((n / 1024 / 1024) > 1024)
                {
                    return CUtils::format_string("%.2f gb", ToG(n));
                }
                else
                {
                    return CUtils::format_string("%.2f mb", ToM(n));
                }
            }
            else
            {
                return CUtils::format_string("%.2f kb", ToK(n));
            }
        }
        else
        {
            return CUtils::format_string("%.2f b", (double)n);
        }
    }
    void Print()
    {
        for (auto it : m_nicInfoList)
        {
            std::cout << it.FriendlyName << std::endl;
            std::cout << it.AdapterName << std::endl;
            std::cout << it.Description << std::endl;
            std::cout << it.MacAddr << std::endl;
            std::cout << it.CurrentIpAddress << std::endl;

            for (auto iit : it.IpAddressMaskList)
            {
                std::cout << iit.first << std::endl;
                std::cout << iit.second << std::endl;
            }
            for (auto git : it.GateAwayIpAddressList)
            {
                std::cout << git << std::endl;
            }
            for (auto dit : it.DNSIpAddressList)
            {
                std::cout << dit << std::endl;
            }
            std::cout << it.BytesLinkSpeed.InBytes / 1000 / 1000 << "m" << std::endl;
            std::cout << it.BytesLinkSpeed.OutBytes / 1000 / 1000 << "m" << std::endl;
        }

        std::cout << "接收大小:" << ToKMG(m_totalBytes.InBytes) << std::endl;
        std::cout << "发送大小:" << ToKMG(m_totalBytes.OutBytes) << std::endl;
        std::cout << "接收速率:" << ToKMG(m_totalBytesPerSecond.InBytes) << "/s" << std::endl;
        std::cout << "发送速率:" << ToKMG(m_totalBytesPerSecond.OutBytes) << "/s" << std::endl;
        for (auto it : m_procStatList)
        {
            std::cout << it.first << std::endl;
            std::cout << ToKMG(it.second.InBytes) << "/s" << std::endl;
            std::cout << ToKMG(it.second.OutBytes) << "/s" << std::endl;
        }
        for (auto it : m_procStatSpeedList)
        {
            std::cout << it.first << std::endl;
            std::cout << ToKMG(it.second.InBytes) << "/s" << std::endl;
            std::cout << ToKMG(it.second.OutBytes) << "/s" << std::endl;
        }
    }
private:
    BOOL GetNetworkProcessStat(std::unordered_map<DWORD, InOutBytes> & procStatList)
    {
        DWORD dwRet = 0;
        PBYTE pTcpTable = NULL;
        DWORD dwTcpTableSize = 0;
        PMIB_TCPTABLE_OWNER_PID pTcpTableIterator = NULL;
        PMIB_TCPROW_OWNER_PID pTcpRow = NULL;
        PTCP_ESTATS_DATA_ROD_v0 dataRod = { 0 };

        dwRet = GetExtendedTcpTable((PMIB_TCPTABLE_OWNER_PID)pTcpTable, &dwTcpTableSize, FALSE, AF_INET, TCP_TABLE_OWNER_PID_ALL, 0);
        if (dwRet == ERROR_INSUFFICIENT_BUFFER) {
            pTcpTable = new BYTE[dwTcpTableSize];
            if (pTcpTable == NULL) {
                printf("Error allocating memory\n");
                return FALSE;
            }
        }
        dwRet = GetExtendedTcpTable((PMIB_TCPTABLE_OWNER_PID)pTcpTable, &dwTcpTableSize, FALSE, AF_INET, TCP_TABLE_OWNER_PID_ALL, 0);
        if (dwRet == ERROR_SUCCESS) {
            pTcpTableIterator = (PMIB_TCPTABLE_OWNER_PID)pTcpTable;
            for (DWORD i = 0; i < (int)pTcpTableIterator->dwNumEntries; i++) {
                pTcpRow = &pTcpTableIterator->table[i];
                if (pTcpRow->dwState == MIB_TCP_STATE_ESTAB)
                {
                    TCP_ESTATS_DATA_ROD_v0 rod = { 0 };
                    dwRet = GetPerTcpConnectionEStats((PMIB_TCPROW)pTcpRow, TcpConnectionEstatsData, NULL, 0, 0, NULL, 0, 0, (PUCHAR)&rod, 0, sizeof(rod));
                    if (dwRet == ERROR_SUCCESS)
                    {
                        auto it = procStatList.find(pTcpRow->dwOwningPid);
                        if (it == procStatList.end())
                        {
                            InOutBytes inOutBytes = {};
                            inOutBytes.InBytes += rod.DataBytesIn;
                            inOutBytes.OutBytes += rod.DataBytesOut;
                            procStatList.emplace(pTcpRow->dwOwningPid, inOutBytes);
                        }
                        else
                        {
                            it->second.InBytes += rod.DataBytesIn;
                            it->second.OutBytes += rod.DataBytesOut;
                        }
                    }
                }
            }
        }

        if (pTcpTable != NULL) {
            delete[]pTcpTable;
            pTcpTable = NULL;
        }
        return TRUE;
    }
    BOOL GetTotalIpStatistics(InOutBytes& totalBytes)
    {
        ULONG dwRet = 0;
        PBYTE pIfTable = NULL;
        PMIB_IFTABLE pIfTableIterator = NULL;
        ULONG ulIfTableSize = 0;
        dwRet = GetIfTable(NULL, &ulIfTableSize, FALSE);
        if (dwRet == ERROR_INSUFFICIENT_BUFFER) {
            pIfTable = new BYTE[ulIfTableSize];
            if (pIfTable == NULL) {
                printf("Error allocating memory\n");
                return 1;
            }
        }
        dwRet = GetIfTable((PMIB_IFTABLE)pIfTable, &ulIfTableSize, FALSE);
        if (dwRet == ERROR_SUCCESS)
        {
            pIfTableIterator = (PMIB_IFTABLE)pIfTable;
            for (DWORD i = 0; i < pIfTableIterator->dwNumEntries; i++)
            {
                PMIB_IFROW pIfRow = &pIfTableIterator->table[i];
                if (pIfRow->dwType <= IF_TYPE_PPP)
                {
                    totalBytes.InBytes += pIfRow->dwInOctets;// *8;
                    totalBytes.OutBytes += pIfRow->dwOutOctets;// *8;
                }
            }
        }
        delete[]pIfTable;
        return TRUE;
    }
};


×
打赏作者
最新回复 (0)
只看楼主
全部楼主
返回