Windows获取网卡信息

前言

&emsp;&emsp;这是一个Qt项目,需求是显示连接网卡的ip,过滤掉断开的和虚拟网卡等。本来想直接使用Qt提供的QNetworkConfigurationManager,但是在虚拟机里面这个接口某些情况无法检测到网卡配置,最后还是采用Windows API稳妥方案解决。WinAPI封装的com接口里面可以使用wmi nic查询网卡硬件相关的信息,但是这个接口主要是提供硬件信息,ip是个保留项,里面没有填充数据。所以还是直接使用<iphlpapi.h>里面接口。

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
#define MALLOC(x) HeapAlloc(GetProcessHeap(), 0, (x))
#define FREE(x) HeapFree(GetProcessHeap(), 0, (x))

#define WORKING_BUFFER_SIZE 15000
#define MAX_TRIES 3
void queryNetcardIP{
DWORD dwRetVal = 0;

unsigned int i = 0;
// Set the flags to pass to GetAdaptersAddresses

ULONG flags = GAA_FLAG_INCLUDE_PREFIX;

// default to unspecified address family (both)
ULONG family = AF_UNSPEC;

PIP_ADAPTER_ADDRESSES pAddresses = NULL;
ULONG outBufLen = 0;
ULONG Iterations = 0;

PIP_ADAPTER_ADDRESSES pCurrAddresses = NULL;

IP_ADAPTER_PREFIX *pPrefix = NULL;
//指定ipv4
family = AF_INET;

// Allocate a 15 KB buffer to start with.
outBufLen = WORKING_BUFFER_SIZE;

do {

pAddresses = (IP_ADAPTER_ADDRESSES *) MALLOC(outBufLen);
if (pAddresses == NULL) {
return;

}
dwRetVal =
GetAdaptersAddresses(family, flags, NULL, pAddresses, &outBufLen);

if (dwRetVal == ERROR_BUFFER_OVERFLOW) {
FREE(pAddresses);
pAddresses = NULL;
} else {
break;
}
Iterations++;

} while ((dwRetVal == ERROR_BUFFER_OVERFLOW) && (Iterations < MAX_TRIES));

if (dwRetVal == NO_ERROR) {
// If successful, output some information from the data we received
pCurrAddresses = pAddresses;
QStringList list;
while (pCurrAddresses) {
//去掉VMWare和VirtualBox创建的虚拟网卡,过滤掉断开连接的网卡(OperStatus=2),过滤掉环回网卡

QString description = QString::fromWCharArray(pCurrAddresses->Description);

if (description.contains("VirtualBox", Qt::CaseInsensitive)
|| description.contains("VMware", Qt::CaseInsensitive)

|| (pCurrAddresses->OperStatus == 2)
|| (pCurrAddresses->IfType == IF_TYPE_SOFTWARE_LOOPBACK))
) {
pCurrAddresses = pCurrAddresses->Next;
continue;
}

pPrefix = pCurrAddresses->FirstPrefix;
if (pPrefix) {
for (i = 0; pPrefix != NULL; i++) {
//一个网卡的里面包含多个ip,网关、真实ip、广播地址等,第二个是真实ip

if (i == 1) {
sockaddr_in *address = (sockaddr_in *) pPrefix->Address.lpSockaddr;
list.append(inet_ntoa(address->sin_addr));
break;
}

pPrefix = pPrefix->Next;
}
}

pCurrAddresses = pCurrAddresses->Next;
}
qInfo() << list;
}
if (pAddresses) {
FREE(pAddresses);
}
}

其实PIP_ADAPTER_ADDRESSES这个结构体里面还有很多其他重要信息,比如网卡速率,网卡类型等。


Windows获取网卡信息
http://yoursite.com/2021/03/28/Windows获取网卡信息/
作者
还在输入
发布于
2021年3月28日
许可协议