微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

关于在 C++ 中获取机器的 Windows IP 地址的任何建议使用 Visual Studio 2019?

如何解决关于在 C++ 中获取机器的 Windows IP 地址的任何建议使用 Visual Studio 2019?

我使用以下示例程序编写了一个程序: https://docs.microsoft.com/en-us/windows/win32/api/iphlpapi/nf-iphlpapi-getadaptersinfo

然而,我面临的问题是,当我列出适配器描述和适配器 IP 地址时,所有 IPv4 地址(包括 VirtualBox 地址)都会显示出来。我们对 Intel(R) Dual Band Wireless-AC 7265 IP 地址感兴趣。

在执行程序时,下面是适配器描述,显示的 IP 地址:

    ComboIndex:     17
    Adapter Name:   {E783F44-FB13-4D75-962E-BB5DE229F1B1}
    Adapter Desc:   VirtualBox Host-Only Ethernet Adapter
    Adapter Addr:   0A-00-28-00-00-13
    Index:  19
    Type:   Ethernet
    IP Address:     192.168.36.1
    IP Mask:        255.255.255.0
    Gateway:        0.0.0.0
    ***
    DHCP Enabled: No
    Have Wins: No

    ComboIndex:     5
    Adapter Name:   {3A58A814-B840-4951-9302-6D2fdb404FF3}
    Adapter Desc:   Intel(R) Dual Band Wireless-AC 7265
    Adapter Addr:   C8-24-58-50-47-32
    Index:  5
    Type:   UnkNown type 71
    IP Address:     192.168.0.106
    IP Mask:        255.255.255.0
    Gateway:        192.168.0.1
    ***
    DHCP Enabled: Yes
      DHCP Server:  192.168.0.1
      Lease Obtained: Tue Jan 19 17:17:51 2021
      Lease Expires:  Fri Apr 17 00:14:00 1970
    Have Wins: No

    ComboIndex:     18
    Adapter Name:   {FB92F018-6F10-47D3-96D6-010DAF3DDEB8}
    Adapter Desc:   Microsoft Wi-Fi Direct Virtual Adapter
    Adapter Addr:   C8-24-58-50-46-34
    Index:  18
    Type:   UnkNown type 71
    IP Address:     0.0.0.0
    IP Mask:        0.0.0.0
    Gateway:        0.0.0.0
    ***
    DHCP Enabled: Yes
      DHCP Server:
      Lease Obtained: Thu Jan  1 05:30:00 1970
      Lease Expires:  Thu Jan  1 05:30:00 1970
    Have Wins: No

    ComboIndex:     12
    Adapter Name:   {7CD8BFA9-ACEB-48CB-A241-D3CA9342EEF4}
    Adapter Desc:   Microsoft Wi-Fi Direct Virtual Adapter #2
    Adapter Addr:   CA-22-58-51-45-35
    Index:  12
    Type:   UnkNown type 71
    IP Address:     0.0.0.0
    IP Mask:        0.0.0.0
    Gateway:        0.0.0.0
    ***
    DHCP Enabled: Yes
      DHCP Server:
      Lease Obtained: Thu Jan  1 05:30:00 1970
      Lease Expires:  Invalid Argument to _localtime32_s
    Have Wins: No

因此,为了仅读取系统的 IP 地址,我修改了程序以搜索除“Microsoft”或“Virtual”之外的字符串(以消除适配器描述)。

这适用于我的系统。但我不相信这是获取机器 IP 地址的最佳方式。

关于如何修改逻辑以获取执行此程序的任何系统的 IP 地址的任何建议,非常感谢!

程序如下:


#include <vector>
#include <iostream>
#include <string.h>

#include <winsock2.h>
#include <iphlpapi.h>
#include <stdio.h>
#include <stdlib.h>

#pragma comment(lib,"IPHLPAPI.lib")

#define MALLOC(x) HeapAlloc(GetProcessHeap(),(x))
#define FREE(x) HeapFree(GetProcessHeap(),(x))

using namespace std;

/* Note: Could also use malloc() and free() */

string getMachineIPAddr()
{
    /* Declare and initialize variables */
    vector<string> adapterName;
    vector<string> adapterDesc;
    vector<string> adapterIpAddr;

    int count = 0;

    // It is possible for an adapter to have multiple
    // IPv4 addresses,gateways,and secondary WINS servers
    // assigned to the adapter. 
    //
    // Note that this sample code only prints out the 
    // first entry for the IP address/mask,and gateway,and
    // the primary and secondary WINS server for each adapter. 

    PIP_ADAPTER_INFO pAdapterInfo;
    PIP_ADAPTER_INFO pAdapter = NULL;
    DWORD dwRetVal = 0;
    UINT i;

    /* variables used to print DHCP time info */
    struct tm newtime;
    char buffer[32];
    errno_t error;
    string err_str = "Err: Exiting function!";

    ULONG ulOutBufLen = sizeof(IP_ADAPTER_INFO);
    pAdapterInfo = (IP_ADAPTER_INFO*)MALLOC(sizeof(IP_ADAPTER_INFO));
    if (pAdapterInfo == NULL) {
        printf("Error allocating memory needed to call GetAdaptersinfo\n");
        return err_str;
    }
    // Make an initial call to GetAdaptersInfo to get
    // the necessary size into the ulOutBufLen variable
    if (GetAdaptersInfo(pAdapterInfo,&ulOutBufLen) == ERROR_BUFFER_OVERFLOW) {
        FREE(pAdapterInfo);
        pAdapterInfo = (IP_ADAPTER_INFO*)MALLOC(ulOutBufLen);
        if (pAdapterInfo == NULL) {
            printf("Error allocating memory needed to call GetAdaptersinfo\n");
            return err_str;
        }
    }

    if ((dwRetVal = GetAdaptersInfo(pAdapterInfo,&ulOutBufLen)) == NO_ERROR) {
        pAdapter = pAdapterInfo;
        while (pAdapter) {
            printf("\tComboIndex: \t%d\n",pAdapter->ComboIndex);
            printf("\tAdapter Name: \t%s\n",pAdapter->AdapterName);
            printf("\tAdapter Desc: \t%s\n",pAdapter->Description);
            printf("\tAdapter Addr: \t");

            adapterName.push_back(pAdapter->AdapterName);
            adapterDesc.push_back(pAdapter->Description);
            adapterIpAddr.push_back(pAdapter->IpAddressList.IpAddress.String);

            for (i = 0; i < pAdapter->AddressLength; i++) {
                if (i == (pAdapter->AddressLength - 1))
                    printf("%.2X\n",(int)pAdapter->Address[i]);
                else
                    printf("%.2X-",(int)pAdapter->Address[i]);
            }
            printf("\tIndex: \t%d\n",pAdapter->Index);
            printf("\tType: \t");
            switch (pAdapter->Type) {
            case MIB_IF_TYPE_OTHER:
                printf("Other\n");
                break;
            case MIB_IF_TYPE_ETHERNET:
                printf("Ethernet\n");
                break;
            case MIB_IF_TYPE_TOKENRING:
                printf("Token Ring\n");
                break;
            case MIB_IF_TYPE_FDDI:
                printf("FDDI\n");
                break;
            case MIB_IF_TYPE_PPP:
                printf("PPP\n");
                break;
            case MIB_IF_TYPE_LOOPBACK:
                printf("Lookback\n");
                break;
            case MIB_IF_TYPE_SLIP:
                printf("Slip\n");
                break;
            default:
                printf("UnkNown type %ld\n",pAdapter->Type);
                break;
            }

            printf("\tIP Address: \t%s\n",pAdapter->IpAddressList.IpAddress.String);
            printf("\tIP Mask: \t%s\n",pAdapter->IpAddressList.IpMask.String);

            printf("\tGateway: \t%s\n",pAdapter->GatewayList.IpAddress.String);
            printf("\t***\n");

            if (pAdapter->DhcpEnabled) {
                printf("\tDHCP Enabled: Yes\n");
                printf("\t  DHCP Server: \t%s\n",pAdapter->Dhcpserver.IpAddress.String);

                printf("\t  Lease Obtained: ");
                /* display local time */
                error = _localtime32_s(&newtime,(__time32_t*)&pAdapter->LeaSEObtained);
                if (error)
                    printf("Invalid Argument to _localtime32_s\n");
                else {
                    // Convert to an ASCII representation 
                    error = asctime_s(buffer,32,&newtime);
                    if (error)
                        printf("Invalid Argument to asctime_s\n");
                    else
                        /* asctime_s returns the string terminated by \n\0 */
                        printf("%s",buffer);
                }

                printf("\t  Lease Expires:  ");
                error = _localtime32_s(&newtime,(__time32_t*)&pAdapter->LeaseExpires);
                if (error)
                    printf("Invalid Argument to _localtime32_s\n");
                else {
                    // Convert to an ASCII representation 
                    error = asctime_s(buffer,buffer);
                }
            }
            else
                printf("\tDHCP Enabled: No\n");

            if (pAdapter->HaveWins) {
                printf("\tHave Wins: Yes\n");
                printf("\t  Primary Wins Server:    %s\n",pAdapter->PrimaryWinsServer.IpAddress.String);
                printf("\t  Secondary Wins Server:  %s\n",pAdapter->SecondaryWinsServer.IpAddress.String);
            }
            else
                printf("\tHave Wins: No\n");
            pAdapter = pAdapter->Next;
            printf("\n");
        }
    }
    else {
        printf("GetAdaptersInfo Failed with error: %d\n",dwRetVal);

    }
    
    // THIS IS CODE TO ELIMINATE ADAPTERS WITH 'MICROSOFT' OR 'VIRTUAL' 
    // IN THE ADAPTER DESCRIPTIONS
    vector<string>::iterator it = adapterDesc.begin();
    vector<string>::iterator it2 = adapterIpAddr.begin();

    string compareStr1 = "Microsoft";
    string compareStr2 = "Virtual";
    string outAdapterDesc = "";
    string outAdapterIPAddr = "";

    for (it = adapterDesc.begin(),it2 = adapterIpAddr.begin(); it != adapterDesc.end(); it++,it2++)
    {
        printf("*it: %s\n",it->c_str());
        printf("*it2: %s\n",it2->c_str());
         
        size_t found = it->find("Microsoft");
        size_t found2 = it->find("Virtual");

        if ((found == string::npos) || (found2 == string::npos))
        {
            outAdapterDesc = *it;
            outAdapterIPAddr = *it2;
        }
    }

    printf("outAdapterDesc: %s\n",outAdapterDesc.c_str());
    printf("outAdapterIPAddr: %s\n",outAdapterIPAddr.c_str());

    if (pAdapterInfo)
        FREE(pAdapterInfo);

    return outAdapterIPAddr;
}


int __cdecl main()
{
    string machineIPAddr = getMachineIPAddr();
    cout << "machineIPAddr: " << getMachineIPAddr() << endl;
}

解决方法

调用 GetBestRoute 以获取到相关 IP 地址的路由,并检查生成的 MIB_IPFORWARDROW::dwForwardIfIndex 接口索引。谷歌在 8.8.8.8 的 DNS 是一个合理的选择。你实际上并没有连接,只是检查如果你尝试会发生什么。您的 VirtualBox 界面将无法达到 8.8.8.8,但 VPN 可以。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。