2015-08-14 72 views
3

因此,我试图寻找几个不同的答案。一,我认为可能有希望是这样的一个:检查以太网上的Windows计算机是否通过C++

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

不过,我真的不知道太多关于网络,甚至有关Windows。就我个人而言,我无法理解他们网站上的大部分Microsoft文档。我尝试了一些东西,比如INetworkConnection,NativeWiFi等。但是他们没有做我想做的事,或者我无法弄清楚如何从可用的文档中做到这一点。

有了这样说,我想用C++,以检查是否该程序正在运行的设备连接到经由以太网电缆互联网。基本上,我要做到以下几点:

  • 如果计算机连接到无线只,运行程序
  • 如果计算机连接到有线只,不运行程序
  • 如果计算机连接到有线和无线,不要运行程序

但是,问题是我不知道如何检查设备是否有以太网连接。有没有办法做到这一点?我没有使用QT。谢谢!编辑:我还应该包括我到目前为止尝试过的东西。

我尝试使用GetAdaptersInfo和获取Type特质从PIP_ADAPTER_INFO变量类型,但总是给我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; 
} 
+0

你有你试图使用GetAdaptersInfo的示例代码?我做的是 –

+0

;我现在将其添加为编辑。对不起,不包括! –

+0

@ Nighthawk441好的 - 我已经包含代码作为编辑。再次,对于之前缺乏代码感到抱歉!感谢您评论:) –

回答

1

你的问题是,因为它可以很复杂,以获得“当前”网络适配器有些困难---这取决于网络适配器配置和目的地的可达性窗口的分组路由让你的“当前”适配器可随时更改.. 。但既然你已经知道了如何获取可用适配器的IP和MAC的(“硬件地址”),你可以简单地使用你的黑客获取一个MAC您当前的IP和过滤器/搜索我的第二个函数中吧!字段“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作为参数上面的函数...

+0

这似乎是一个很好的答案,但不幸的是我有点困惑。一旦我像第二个代码块一样遍历矢量,行的很多属性都是相同的。我如何区分无线和有线?我如何知道用户是否连接到以太网?我试过使用物理地址属性,但这些似乎没有给我一个MAC地址,所以我不确定要比较的是什么。对困惑感到抱歉。谢谢! –

+0

好吧,经过一些实验后,我得到了这个答案的工作。我将if语句更改为if(row.Type == IF_TYPE_ETHERNET_CSMACD && row.MediaConnectState == MdiaConnectStateConnected),然后在if语句中返回true。非常感谢您的时间和帮助。我现在会接受这个答案。 –

+0

^附录:我也改变了我发送给'getDevices'函数的参数是'NdisPhysicalMedium802_3' –

0

所以首先代码,谢谢非常感谢用户@ Nighthawk441为我指出了正确的方向。没有这个用户,我肯定还没有想出一个解决方案。

这就是说,我现在所拥有的解决方案充其量只是一种破解。它似乎工作,但我认为它甚至不接近最佳选择。因此,我会将此作为答案,但如果发现更好的答案,我将不会接受它。我也很乐意接受任何人的评论,因为它与这个答案有关。

总之,我所做的是我经历了所有的适配器环从GetAdaptersInfo。为了查看适配器是否已连接,我将适配器的IP地址与字符串"0.0.0.0"进行了比较,就好像它不是这个一样,我觉得可以安全地说适配器已连接。所以,不用再说了,这里是我实现的代码。

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 needed to call GetAdaptersInfo"); 

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

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

      string ip_string = pAdapter->IpAddressList.IpAddress.String; 

      switch(pAdapter->Type){ 
       case MIB_IF_TYPE_OTHER: 
        printf("Other\n"); 
        break; 
       ... 
       case MIB_IF_TYPE_ETHERNET: 
        printf("Ethernet\n"); 

        //new code 
        if(ip_string.compare("0.0.0.0") != 0){ 
         free(pAdapterInfo); 
         return true; 
        } 

        break; 
       default: 
        printf("Unknown type %ld\n", pAdapter->Type); 
        break; 
      } 
     }while(pAdapterInfo = pAdapterInfo->Next); 
    } 

    if(pAdapterInfo) 
     free(pAdapterInfo); 

    return false; 
} 

看着这个参考真的帮了我:

https://msdn.microsoft.com/en-us/library/windows/desktop/aa365819%28v=vs.85%29.aspx

所以,谢谢你夜鹰,用于提供信息给我。希望这会帮助别人!如果有人有任何意见或任何其他答案,请随时发布!谢谢!

+1

我认为这应该是C++?这段代码充满了令人厌恶的手动内存管理terribadness。 – Puppy

+0

其初学者的尝试......不审判他还没有 - 而不是非常详细指出的缺陷,并提供其如何完成的例子。 – specializt

+0

@Puppy该代码表面上直接从我在我的答案中提到的MSDN引用中复制。我已经总共添加了一个[免费(...)]声明。如果内存管理是一个问题,那么我将不得不转向并说这是MSDN文档的问题。 –

相关问题