根据GetAdaptersInfo()如何区分网卡类型

时间:2024-03-08 20:00:38

网卡可分为物理网卡与虚拟网卡,其中物理网卡又可分为有线网卡和无线网卡,还有蓝牙设备的网卡。

概念理解:简单的说,物理网卡就是硬件,虚拟网卡是软件。详细点说,物理网卡就是安装在电脑主板上的有线或无线网卡,每块物理网卡都有不同的且唯一的物理地址(MAC地址);虚拟网卡则是通过软件模拟网络环境,构建的虚拟网络适配器,一般是Microsoft Loopback Adapter,通过VPN技术实现虚拟网卡间的局域网通信。

GetAdaptersInfo(pAdapterInfo, &ulOutBufLen)可以获得本机网卡的所有信息,我们可以通过它来过滤得到想要的信息。

pAdapter->Type == MIB_IF_TYPE_ETHERNET    //以太网卡(有线、无线、蓝牙)

pAdapter->Type == 71                                  //无线网卡

strstr(pAdapter->Description,"Bluetooth") >0  //蓝牙设备的网卡(蓝牙的网卡属于以太网卡,但却不属于有线网卡和无线网卡)

strstr(pAdapter->Description,"PCI")>0            //物理网卡

这种方法基本达到识别的目的,但是也存在不能识别网卡类型的可能,这就要根据项目的需求来决定是否采用此种方法。

下面的例子是获取本地有线物理网卡的mac地址:

 1 #pragma once 
 2 #include "UserInfo.h"
 3 #include <stdio.h>
 4 #include <winsock2.h>
 5 #include <iphlpapi.h>
 6 #pragma comment(lib, "IPHLPAPI.lib")
 7 
 8 int GetMac(char* mac)
 9 {
10     ULONG ulOutBufLen = sizeof(IP_ADAPTER_INFO);
11     PIP_ADAPTER_INFO pAdapterInfo = (IP_ADAPTER_INFO*)malloc(sizeof(IP_ADAPTER_INFO));
12     if(pAdapterInfo == NULL)
13         return -1;
14     if(GetAdaptersInfo(pAdapterInfo, &ulOutBufLen) == ERROR_BUFFER_OVERFLOW) 
15     {
16         free(pAdapterInfo);
17         pAdapterInfo = (IP_ADAPTER_INFO *)malloc(ulOutBufLen);
18         if (pAdapterInfo == NULL) 
19             return -2;
20     }
21 
22     if(GetAdaptersInfo(pAdapterInfo, &ulOutBufLen) == NO_ERROR)
23     {
24         for(PIP_ADAPTER_INFO pAdapter = pAdapterInfo; pAdapter != NULL; pAdapter = pAdapter->Next)
25         {
26             // 确保是有线物理网卡 
27             if(pAdapter->Type != MIB_IF_TYPE_ETHERNET || pAdapter->Type == 71 || strstr(pAdapter->Description,"Bluetooth") >0)
28                 continue;
29             if(pAdapter->AddressLength != 6)
30                 continue;
31             sprintf_s(mac, 18, "%02X:%02X:%02X:%02X:%02X:%02X",
32                 int (pAdapter->Address[0]),
33                 int (pAdapter->Address[1]),
34                 int (pAdapter->Address[2]),
35                 int (pAdapter->Address[3]),
36                 int (pAdapter->Address[4]),
37                 int (pAdapter->Address[5]));
38             break;
39         }
40     }
41     free(pAdapterInfo);
42 
43     return 0;
44 }
View Code

 

我在网上看到有人分享另一个方法,那就是通过“Characteristics”这个值来确定网卡的类型是虚拟网卡还是物理网卡,据说更简单而且100%准确。

虽然我自己还没实践过,不过也暂时将这种方法记录下来~

Characteristics 值在注册表HKEY_LOCAL_MACHINE/SYSTEM/CurrentControlSet/Control/Class/{4D36E972-E325-11CE-BFC1-08002bE10318}/数字下。
在windows中,Characteristics 的取值如下,Characteristics项可以有1个或多个如下的值(多值应计算总和):
十六进制值                  名字                                                      描述
ox1                   NCF_VIRTUAL                                           说明组件是个虚拟适配器
ox2                   NCF_SOFTWARE_ENUMERATED           说明组件是一个软件模拟的适配器
ox4        NCF_PHYSICAL                                      说明组件是一个物理适配器
ox8        NCF_HIDDEN              说明组件不显示用户接口
ox10      NCF_NO_SERVICE            说明组件没有相关的服务(设 备驱动程序)
ox20      NCF_NOT_USER_REMOVABLE          说明不能被用户删除(例如, 通过控制面板或设备管理器)
ox40      NCF_MULTIPORT_INSTANCED_ADAPTER 说明组件有多个端口,每个端口作为单独的设备安装。
ox80      NCF_HAS_UI                                              说明组件支持用户接口(例如,Advanced Page或Customer Properties Sheet)
ox400      NCF_FILTER                                                说明组件是一个过滤器
从上面可以看出来,只要用户判断“Characteristics ”的值就可以判断网卡是虚拟网卡还是物理网卡。
如果是虚拟网卡:Characteristics & NCF_VIRTUAL ==NCF_VIRTUAL
如果是物理网卡:Characteristics & NCF_PHYSICAL ==NCF_PHYSICAL