c++ - 检查以太网上的 Windows 计算机是否通过 C++

标签 c++ windows wireless ethernet

因此,我尝试查看了几个不同的答案。我认为可能有希望的是这个:

How to check network interface type is Ethernet or Wireless on Windows using Qt?

但是,我对网络甚至 Windows 都不是很了解。就个人而言,我无法理解他们网站上的大部分 Microsoft 文档。我已经尝试过 INetworkConnectionNativeWiFi 等。但要么他们没有按照我的意愿行事,要么我只是无法从可用文档中弄清楚如何做。

话虽如此,我想使用 C++ 检查运行此程序的设备是否通过以太网电缆连接到互联网。基本上,我想执行以下操作:

  • 如果计算机仅连接到无线,则运行程序
  • 如果计算机仅连接到有线,请不要运行该程序
  • 如果计算机同时连接有线和无线,请不要运行该程序

但是,问题是我不知道如何检查设备是否连接了以太网。有没有办法做到这一点?我没有使用 QT。谢谢!


编辑:我还应该包括到目前为止我尝试过的内容。

我尝试使用 GetAdaptersInfo 并从 PIP_ADAPTER_INFO 变量类型获取 Type 特征,但这总是给我 Unknown type 71 无论我是否在以太网上。

GetAdaptersInfo 的文档在这里: https://msdn.microsoft.com/en-us/library/aa365917%28VS.85%29.aspx

谢谢


编辑 2:这是我用于 GetAdaptersInfo 的代码

bool is_on_ethernet{
    PIP_ADAPTER_INFO pAdapterInfo;
    PIP_ADAPTER_INFO pAdapter = NULL;
    DWORD dwRetVal = 0;
    UINT i;

    struct tm newtime;
    char buffer[32];
    errno_t error;

    ULONG ulOutBufLen = sizeof(IP_ADAPTER_INFO);
    pAdapterInfo = (IP_ADAPTER_INFO *)malloc(sizeof(IP_ADAPTER_INFO));

    if(pAdapterInfo == NULL)
        printf("Error allocating memory need to call GetAdaptersInfo");

    if(GetAdaptersInfo(pAdapterInfo, &ulOutBufLen) == ERROR_BUFFER_OVERFLOW){
        free(pAdapterInfo);
        pAdapterInfo = (IP_ADAPTER_INFO *)malloc(ulOutBufLen);
    }

    if((dwRetVal = GetAdaptersInfo(pAdapterInfo, &ulOutBufLen)) == NO_ERROR){
        pAdapter = pAdapterInfo;

        switch(pAdapter->Type){
            case MIB_IF_TYPE_OTHER:
                printf("Other\n");
                return false;
                break;
            case MIB_IF_TYPE_ETHERNET:
                printf("Ethernet\h");
                return true;
                break;
            case MIB_IF_TYPE_TOKENRING:
                printf("Token Ring\n");
                return false;
                break;
            case MIB_IF_TYPE_FDDI
                printf("FDDI\n");
                return false;
                break;
            case MIB_IF_TYPE_PPP
                printf("PPP\n");
                return false;
                break;
            case MIB_IF_TYPE_LOOPBACK
                printf("Lookback\n");
                return false;
                break;
            case MIB_IF_TYPE_SLIP
                printf("Slip\n");
                return false;
                break;
            default
                printf("Unknown type %ld\n\n", pAdapter->Type);
                return false;
                break;
        }
    }

    if(pAdapterInfo)
        free(pAdapterInfo);

    return false;
}

最佳答案

您的问题有点困难,因为获取“当前”网络适配器可能真的很复杂 --- Windows 根据网络适配器配置和目标可达性路由数据包,因此您的“当前”适配器可能随时更改 ...但是由于您已经知道如何检索可用适配器的 IP 和 MAC(“硬件地址”),您可以简单地使用 hack 检索当前 IP 的 MAC 并在我的第二个函数中过滤/搜索它! “PhysicalAddress”字段是您要查找的内容,即 MAC 地址

我的经验是,唯一可靠的方法是通过 GetIfTableGetIfTable2 , 前者有所返回 superficial adpater info后者提供了很好的detail . 这是一个示例实现,因为它使用了详细的功能,您还可以查询 WLAN 适配器:

vector<MIB_IF_ROW2>* getDevices(NDIS_PHYSICAL_MEDIUM type)
    {       
        vector<MIB_IF_ROW2> *v = new vector<MIB_IF_ROW2>();
        PMIB_IF_TABLE2 table = NULL;
        if(GetIfTable2Ex(MibIfTableRaw, &table) == NOERROR && table)
        {
            UINT32 i = 0;
            for(; i < table->NumEntries; i++)
            {
                MIB_IF_ROW2 row;

                ZeroMemory(&row, sizeof(MIB_IF_ROW2));
                row.InterfaceIndex = i;
                if(GetIfEntry2(&row) == NOERROR)
                {                   
                    if(row.PhysicalMediumType == type)
                    {
                        v->push_back(row);
                    }                   
                }           
            }
            FreeMibTable(table);
        }
        return v;
    }

现在您需要做的就是遍历列表并过滤掉禁用的适配器和诸如此类的东西:

vector<MIB_IF_ROW2>* wlan = getDevices(NdisPhysicalMediumNative802_11); //WLAN adapters
//see https://msdn.microsoft.com/en-us/library/windows/desktop/aa814491(v=vs.85).aspx, "PhysicalMediumType" for a full list
for(auto &row : *v)
    {
        //do some additional filtering, this needs to be changed for non-WLAN           
        if( row.TunnelType == TUNNEL_TYPE_NONE &&
            row.AccessType != NET_IF_ACCESS_LOOPBACK &&         
            row.Type == IF_TYPE_IEEE80211 &&
            row.InterfaceAndOperStatusFlags.HardwareInterface == TRUE)              
            {
                //HERE BE DRAGONS!                    
            }
    }

现在很容易生成 WLAN 适配器和非 WLAN 适配器列表(请参阅第二个函数中的注释),搜索您当前的 MAC 并得出它是有线或无线的结论 - 但请注意自 802.11 以来,这些列表可能重叠基本上是 802.3 的扩展版本但是 802.3 包括 802.11 (因为它是一个扩展) - 所以您需要按顺序执行一些 if/else 逻辑将 WLAN 与非 WLAN 适配器分开。

你也可以使用 WlanEnumInterfaces获取所有 WLAN 适配器,但这与使用上述函数和 NdisPhysicalMediumNative802_11 作为参数基本相同 ...

关于c++ - 检查以太网上的 Windows 计算机是否通过 C++,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32016166/

相关文章:

c++ - 私有(private)嵌套类 c++ 的实例

c++11 参数包错误行为与 Apple LLVM 7.0.0 但适用于 GCC-5.1

c++ - Windows 中的 Control+Z 表示输入 C++ 结束?

android-intent - 以编程方式设置或查看 "Advanced Wi-fi"设置

linux - 试图阅读 iw_statistics 但代码不起作用?

c++ - const 关键字在方法声明中的不同位置?

c++ - 无法将元素添加到共享指针的线程安全锁定队列中

c# - 如何知道网络接口(interface)何时在 C# 中使用路由器作为 DNS 服务器?

windows - 如何在电脑开机时启动批处理文件

c - 在 C 代码中包含 wpa_ctrl.h