zoukankan      html  css  js  c++  java
  • 使用 GetAdaptersInfo 或 GetAdaptersAddresses 获取网络相关参数

    GetAdaptersInfo 和 GetAdaptersAddresses 都能获取网络相关信息,如网卡名称、MAC 地址、IP、DNS、网关等信息,但是两个函数感觉都有一些问题,GetAdaptersInfo 获取不到 IPV6 地址信息,使用起来较为简单,GetAdaptersAddresses 可以获取到 IPV6 地址信息,但是似乎获取不到 子网掩码 ,MSDN 推荐使用 GetAdaptersAddresses 。

    1、GetAdaptersInfo:
    代码:

    PIP_ADAPTER_INFO pAdapterInfo;
    PIP_ADAPTER_INFO pAdapter = NULL;
    DWORD errValue = 0;
    ULONG ulOutBufLen = sizeof(IP_ADAPTER_INFO);
    pAdapterInfo = (IP_ADAPTER_INFO *)malloc(sizeof(IP_ADAPTER_INFO));
    if (!pAdapterInfo)//malloc失败
        return;
    if (GetAdaptersInfo(pAdapterInfo, &ulOutBufLen) == ERROR_BUFFER_OVERFLOW) //空间不够,重新分配
    {
        free(pAdapterInfo);
        pAdapterInfo = (IP_ADAPTER_INFO *)malloc(ulOutBufLen);
        if (!pAdapterInfo) //malloc失败
            return;
    }
    CString info;
    if ((errValue = GetAdaptersInfo(pAdapterInfo, &ulOutBufLen)) == NO_ERROR)
    {
        pAdapter = pAdapterInfo;
        while (pAdapter)
        {
            info += CString(_T("Adapter Name:")) + CString(pAdapter->AdapterName) + CString(_T("
    "));//名字
            info += CString(_T("Adapter Desc:")) + CString(pAdapter->Description) + CString(_T("
    "));//描述
            CString mac;
            mac.Format(_T("%02X%02X%02X%02X%02X%02X"), pAdapter->Address[0], pAdapter->Address[1], 
                pAdapter->Address[2], pAdapter->Address[3], pAdapter->Address[4], pAdapter->Address[5]);
            info += CString(_T("Adapter Mac:")) + mac + CString(_T("
    "));//MAC地址
            CString type;
            switch (pAdapter->Type) //类型,列举了几种
            {
            case MIB_IF_TYPE_OTHER:
                type = _T("其他");
                break;
            case MIB_IF_TYPE_ETHERNET:
                type = _T("以太网接口");
                break;
            case IF_TYPE_ISO88025_TOKENRING:
                type = _T("ISO88025令牌环");
                break;
            case MIB_IF_TYPE_PPP:
                type = _T("PPP接口");
                break;
            case MIB_IF_TYPE_LOOPBACK:
                type = _T("软件回路接口");
                break;
            case MIB_IF_TYPE_SLIP:
                type = _T("ATM网络接口");
                break;
            case IF_TYPE_IEEE80211:
                type = _T("无线网络接口");
                break;
            default:
                type = _T("未知接口");
                break;
            }
            info += CString(_T("网卡类型:")) + type + CString(_T("
    "));
            info += CString(_T("IP地址:")) + CString(pAdapter->IpAddressList.IpAddress.String) + CString(_T("
    "));
            info += CString(_T("子网掩码:")) + CString(pAdapter->IpAddressList.IpMask.String) + CString(_T("
    "));
            info += CString(_T("默认网关:")) + CString(pAdapter->GatewayList.IpAddress.String) + CString(_T("
    "));
            info += CString(_T("是否DHCP:")) + CString(pAdapter->DhcpEnabled ? _T("是") : _T("否")) + CString(_T("
    "));
            info += CString(_T("DHCP地址:")) + CString(pAdapter->DhcpServer.IpAddress.String) + CString(_T("
    "));
            //Dns
            IP_PER_ADAPTER_INFO* pPerAdapt = NULL;
            ULONG ulLen = 0;
            int err = GetPerAdapterInfo(pAdapter->Index, pPerAdapt, &ulLen);
            if (err == ERROR_BUFFER_OVERFLOW)
            {
                pPerAdapt = (IP_PER_ADAPTER_INFO*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, ulLen);
                err = GetPerAdapterInfo(pAdapter->Index, pPerAdapt, &ulLen);
                if (err == ERROR_SUCCESS)
                {
                    IP_ADDR_STRING* pNext = &(pPerAdapt->DnsServerList);
                    if (pNext && strcmp(pNext->IpAddress.String, "") != 0)//手动DNS
                    {
                        info = info + CString(_T("DNS:")) + CString(pNext->IpAddress.String) + _T("
    ");
                        if (pNext->Next)
                        {
                            pNext = pNext->Next;
                            info = info + CString(_T("备用DNS:")) + CString(pNext->IpAddress.String) + _T("
    ");
                        }
                    }
                }
                HeapFree(GetProcessHeap(), HEAP_ZERO_MEMORY, pPerAdapt);
            }
            info += "
    ";
            pAdapter = pAdapter->Next;
        }
    }
    else
    {
        CString s;
        s.Format(_T("GetAdaptersInfo failed with error: %d
    "), errValue);
        info += s;
    }
    if (pAdapterInfo)
        free(pAdapterInfo);
    SetDlgItemText(IDC_EDIT, info);
    

    效果:

    2、GetAdaptersAddresses:
    代码:

    //关于这个标志,查 MSDN 吧。。。
    ULONG flags = GAA_FLAG_INCLUDE_PREFIX | GAA_FLAG_INCLUDE_GATEWAYS;//包括 IPV4 ,IPV6 网关
    ULONG family = AF_UNSPEC;//返回包括 IPV4 和 IPV6 地址
    PIP_ADAPTER_ADDRESSES pAddresses = NULL;
    ULONG outBufLen = 0;
    DWORD dwRetVal = 0;
    PIP_ADAPTER_ADDRESSES pCurrAddresses = NULL;
    PIP_ADAPTER_UNICAST_ADDRESS pUnicast = NULL;
    PIP_ADAPTER_ANYCAST_ADDRESS pAnycast = NULL;
    PIP_ADAPTER_MULTICAST_ADDRESS pMulticast = NULL;
    IP_ADAPTER_DNS_SERVER_ADDRESS *pDnServer = NULL;
    IP_ADAPTER_PREFIX *pPrefix = NULL;
    outBufLen = 15000;
    do
    {
        pAddresses = (IP_ADAPTER_ADDRESSES *)malloc(outBufLen);
        if (pAddresses == NULL)
            return;
        dwRetVal = GetAdaptersAddresses(family, flags, NULL, pAddresses, &outBufLen);
        if (dwRetVal == ERROR_BUFFER_OVERFLOW)
        {
            free(pAddresses);
            pAddresses = NULL;
        }
        else
            break;
    } while (dwRetVal == ERROR_BUFFER_OVERFLOW);
    CString info;
    if (dwRetVal == NO_ERROR)
    {
        pCurrAddresses = pAddresses;
        while (pCurrAddresses)
        {
            info += CString(_T("Adapter name:")) + pCurrAddresses->AdapterName + CString(_T("
    "));
            info += CString(_T("Description:")) + CString(pCurrAddresses->Description) + CString(_T("
    "));
            info += CString(_T("Friendly name:")) + CString(pCurrAddresses->FriendlyName) + CString(_T("
    "));
            if (pCurrAddresses->PhysicalAddressLength != 0)
            {
                CString mac;//其实 MAC 地址的长度存在 PhysicalAddressLength 中,最好用它来确定格式化的长度
                mac.Format(_T("%02X%02X%02X%02X%02X%02X"), pCurrAddresses->PhysicalAddress[0], pCurrAddresses->PhysicalAddress[1], 
                    pCurrAddresses->PhysicalAddress[2], pCurrAddresses->PhysicalAddress[3], pCurrAddresses->PhysicalAddress[4], 
                    pCurrAddresses->PhysicalAddress[5]);
                info += CString(_T("Adapter Mac:")) + mac + CString(_T("
    "));//MAC地址
            }
            CString type;
            switch (pCurrAddresses->IfType) //类型,列举了几种
            {
            case MIB_IF_TYPE_ETHERNET:
                type = _T("以太网接口");
                break;
            case MIB_IF_TYPE_PPP:
                type = _T("PPP接口");
                break;
            case MIB_IF_TYPE_LOOPBACK:
                type = _T("软件回路接口");
                break;
            case MIB_IF_TYPE_SLIP:
                type = _T("ATM网络接口");
                break;
            case IF_TYPE_IEEE80211:
                type = _T("无线网络接口");
                break;
            }
            info += CString(_T("网卡类型:")) + type + CString(_T("
    "));
            pUnicast = pCurrAddresses->FirstUnicastAddress;
            while (pUnicast)//单播IP
            {
                CHAR IP[130] = { 0 };
                if (AF_INET == pUnicast->Address.lpSockaddr->sa_family)// IPV4 地址,使用 IPV4 转换
                    inet_ntop(PF_INET, &((sockaddr_in*)pUnicast->Address.lpSockaddr)->sin_addr, IP, sizeof(IP));
                else if (AF_INET6 == pUnicast->Address.lpSockaddr->sa_family)// IPV6 地址,使用 IPV6 转换
                    inet_ntop(PF_INET6, &((sockaddr_in6*)pUnicast->Address.lpSockaddr)->sin6_addr, IP, sizeof(IP));
                info += CString(_T("单播IP:")) + CString(IP) + CString(_T("
    "));
                pUnicast = pUnicast->Next;
            }
            if (pCurrAddresses->Dhcpv4Server.lpSockaddr)//DHCP服务器地址
            {
                CHAR dhcp[130] = { 0 };
                if (AF_INET == pCurrAddresses->Dhcpv4Server.lpSockaddr->sa_family)
                    inet_ntop(PF_INET, &((sockaddr_in*)pCurrAddresses->Dhcpv4Server.lpSockaddr)->sin_addr, dhcp, sizeof(dhcp));
                else if (AF_INET6 == pCurrAddresses->Dhcpv4Server.lpSockaddr->sa_family)
                    inet_ntop(PF_INET6, &((sockaddr_in6*)pCurrAddresses->Dhcpv4Server.lpSockaddr)->sin6_addr, dhcp, sizeof(dhcp));
                info += CString(_T("DHCP地址:")) + CString(dhcp) + CString(_T("
    "));
            }
            pDnServer = pCurrAddresses->FirstDnsServerAddress;
            while (pDnServer)//DNS
            {
                CHAR DNS[130] = { 0 };
                if (AF_INET == pDnServer->Address.lpSockaddr->sa_family)
                    inet_ntop(PF_INET, &((sockaddr_in*)pDnServer->Address.lpSockaddr)->sin_addr, DNS, sizeof(DNS));
                else if (AF_INET6 == pDnServer->Address.lpSockaddr->sa_family)
                    inet_ntop(PF_INET6, &((sockaddr_in6*)pDnServer->Address.lpSockaddr)->sin6_addr, DNS, sizeof(DNS));
                info += CString(_T("DNS:")) + CString(DNS) + CString(_T("
    "));
                pDnServer = pDnServer->Next;
            }
            CString MTU;// MTU 
            MTU.Format(_T("MTU:%d
    "), pCurrAddresses->Mtu);
            info += MTU;
            CString sendSpeend;//发送速率
            sendSpeend.Format(_T("send speed:%d
    "), pCurrAddresses->TransmitLinkSpeed);
            info += sendSpeend;
            CString recvSpeed;//接收速率
            recvSpeed.Format(_T("recv speed:%d
    "), pCurrAddresses->ReceiveLinkSpeed);
            info += recvSpeed;
            auto pGetway = pCurrAddresses->FirstGatewayAddress;
            while (pGetway)//网关
            {
                CHAR getway[130] = { 0 };
                if (AF_INET == pGetway->Address.lpSockaddr->sa_family)
                    inet_ntop(PF_INET, &((sockaddr_in*)pGetway->Address.lpSockaddr)->sin_addr, getway, sizeof(getway));
                else if (AF_INET6 == pGetway->Address.lpSockaddr->sa_family)
                    inet_ntop(PF_INET6, &((sockaddr_in6*)pGetway->Address.lpSockaddr)->sin6_addr, getway, sizeof(getway));
                info += CString(_T("Getway:")) + CString(getway) + CString(_T("
    "));
                pGetway = pGetway->Next;
            }
            if (pCurrAddresses->Dhcpv6Server.lpSockaddr)//IPV6DHCP
            {
                CHAR dhcpv6[130] = { 0 };
                if (AF_INET6 == pCurrAddresses->Dhcpv6Server.lpSockaddr->sa_family)
                {
                    inet_ntop(PF_INET6, &((sockaddr_in6*)pCurrAddresses->Dhcpv6Server.lpSockaddr)->sin6_addr, dhcpv6, sizeof(dhcpv6));
                    info += CString(_T("DHCPV6:")) + CString(dhcpv6) + CString(_T("
    "));
                }
            }
            info += CString(_T("
    "));
            pCurrAddresses = pCurrAddresses->Next;
        }
    }
    else
    {
        CString s;
        s.Format(_T("GetAdaptersAddresses failed,error code:%d"), GetLastError());
        AfxMessageBox(s);
    }
    if (pAddresses)
        free(pAddresses);
    SetDlgItemText(IDC_EDIT, info);
    

    效果:

    另外,使用 GetAdaptersAddresses 需要使用 iphlpapi.lib ,需要包含对应头文件,使用 inet_ntop 转换地址时需要包含 WS2tcpip.h 。

    include <WS2tcpip.h>

    include <iphlpapi.h>

    pragma comment(lib, "iphlpapi.lib")

    小结:
    GetAdaptersInfo 使用较为简单,大部分情况下可以满足需求,GetAdaptersAddresses 使用复杂得多,但是可以获取 IPV6 甚至组播地址等。

    代码链接:
    VS2015工程:http://download.csdn.net/detail/yangyang031213/9891542
    https://github.com/yangyang0312/cpp/tree/master/windows/AdaptInfo
    ————————————————
    版权声明:本文为CSDN博主「yangyang031213」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
    原文链接:https://blog.csdn.net/yangyang031213/article/details/64906437

  • 相关阅读:
    第七章第五题(打印不同的教)(Print distinct numbers)
    第七章第四题(分析成绩)(Analyze scores)
    第七章第三题(计算数字的出现次数)(Count occurrence of numbers)
    第七章第二题(倒置输入的数)(Reverse the numbers entered)
    第七章第一题(指定等级)(Assign grades)
    第六章第三十九题(几何:点的位置)(Geometry: point position)
    第六章第三十八题(生成随机字符)(Generate random characters)
    Java提示错误: 找不到或无法加载主类
    第六章第三十七题(格式化整数)(Format an integer)
    第六章第三十六题(几何:正多边形的面积)(Geometry: area of a regular polygon)
  • 原文地址:https://www.cnblogs.com/qing123/p/13223027.html
Copyright © 2011-2022 走看看