网卡可分为物理网卡与虚拟网卡,其中物理网卡又可分为有线网卡和无线网卡,还有蓝牙设备的网卡。
概念理解:简单的说,物理网卡就是硬件,虚拟网卡是软件。详细点说,物理网卡就是安装在电脑主板上的有线或无线网卡,每块物理网卡都有不同的且唯一的物理地址(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 }
我在网上看到有人分享另一个方法,那就是通过“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