【网络编程】【Windows】获取网卡数量

概述:获取虚拟网卡的个数、网卡保活、判断网卡是否存在

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
int GetNetCardNums()
{
int nRet = 0;
CoInitialize(NULL);
INetConnectionManager* pNetManager;
INetConnection* pNetConnection;
IEnumNetConnection* pEnum;

ULONG celtFetched;
std::string strComGuid;
NETCON_PROPERTIES* properties = nullptr;
bool bIsInstalledNcCard = false;
TapReg setRegGuid = get_tap_reg();
NcStatusList ncStausList;

if (setRegGuid.size() == 0)
{
SP_LOGW("%s Reg Not Found, Re Install", __SP_FUNC__);
return 0;
}

if (S_OK != CoCreateInstance(CLSID_ConnectionManager, NULL, CLSCTX_SERVER, IID_INetConnectionManager, (void**)&pNetManager))
{
SP_LOGW("%s Com Instance Failed, sleep(5s)", __SP_FUNC__);

return 0;
}

pNetManager->EnumConnections(NCME_DEFAULT, &pEnum);
pNetManager->Release();
if (NULL == pEnum)
{
return 0;
}

while (pEnum->Next(1, &pNetConnection, &celtFetched) == S_OK)
{
pNetConnection->GetProperties(&properties);

strComGuid = GUIDToString(properties->guidId);

// 查看当前网卡与注册表的guid一致时的状态
for (auto& it : setRegGuid)
{
// #1 判断是否安装了 虚拟网卡
if (strComGuid.compare(it) == 0)
{
nRet++;
}
}
}
pEnum->Release();

return nRet;
}

网卡保活

声明

1
2
3
4
5
6
7
/*
* @fn keepAlive
* @brief 网络连接保活
*
* @detail 线程,通过COM组件实现
*/
void keepDeviceTAVnicAlive();

实现

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
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159


void keepDeviceTAVnicAlive()
{
std::lock_guard<std::mutex> lock(g_mutex);

bool bRet = false;
static int iRePtunFlag = 1; // Nc重连标志
static int iReLoadFlag = 1; // Dll重载标志

// ipc 主要处理nc发送的消息
TrustSpaceIPCUtil m_ncIpc("trustNcToCore");
m_ncIpc.Initialize(&HandleIpcCallBack);

do
{
CoInitialize(NULL);
INetConnectionManager* pNetManager = nullptr;
INetConnection* pNetConnection = nullptr;
IEnumNetConnection* pEnum = nullptr;

ULONG celtFetched;
std::string strComGuid;
bool bIsInstalledNcCard = false;
TapReg setRegGuid = get_tap_reg();
NcStatusList ncStausList;

if (setRegGuid.size() == 0)
{
SP_LOGW("%s Reg Not Found, Re Install", __SP_FUNC__);

goto __REINSTALL;
}

if (S_OK != CoCreateInstance(CLSID_ConnectionManager, NULL, CLSCTX_SERVER, IID_INetConnectionManager, (void**)&pNetManager))
{
SP_LOGW("%s Com Instance Failed, sleep(5s)", __SP_FUNC__);

std::this_thread::sleep_for(std::chrono::milliseconds(1000 * 5));

continue;
}

pNetManager->EnumConnections(NCME_DEFAULT, &pEnum);
if (pNetManager)
{
pNetManager->Release();
pNetManager = nullptr;
}

if (NULL == pEnum)
{
return;
}

while (pEnum->Next(1, &pNetConnection, &celtFetched) == S_OK)
{
NETCON_PROPERTIES* properties = nullptr;

pNetConnection->GetProperties(&properties);

if (properties != nullptr)
{
strComGuid = GUIDToString(properties->guidId);

// T1 查看当前网卡与注册表的guid一致时的状态
for (auto& it : setRegGuid)
{
// #1 判断是否安装了 虚拟网卡
int minSize = min(strComGuid.size(), it.size());
if (it.compare(0, minSize, strComGuid, 0, minSize) == 0)
{
ncStausList[properties->Status] = properties->pszwDeviceName;

// #2 已安装
bIsInstalledNcCard = true;

// #3 判断是否被禁用
if (NCS_DISCONNECTED == properties->Status)
{
pNetConnection->Connect();
SP_LOGI("%s [NcCard] ReConnect", __SP_FUNC__);
}
}
}
}

if (pNetConnection)
{
pNetConnection->Release();
pNetConnection = nullptr;
}
}

if (pEnum)
{
pEnum->Release();
pEnum = nullptr;
}

// T2 网卡启用时,判断是否有业务需要开启
if (g_sp_trust_model && g_sp_trust_model->Session()->NeedsL3Tunnel() && // 有三层业务
!g_sp_trust_model->Session()->IsTunnelSvrsEmpty() && // 服务不为空
g_sp_trust_model->Session()->IsOnline() && // 会话在线
g_bNetWorkOnline) // 必须联网
{
iRePtunFlag = (iRePtunFlag > 300) ? 0 : ++iRePtunFlag;
if (ncStausList.find(NCS_CONNECTED) == ncStausList.end() && (iRePtunFlag % 30 == 0))
{
SP_LOGI("%s [NcCard] Auto Detect ReConnect PTUN", __SP_FUNC__);

if (iReLoadFlag == 5)
{
SP_LOGI("%s [NcCard] Auto Detect ReConnect PTUN FAILED. RUN TIMES OVER 5, NECT:[NO OPTION]", __SP_FUNC__);
}

handleReStartNc();

Sleep(5 * 1000);

iReLoadFlag++;
}
else if (ncStausList.find(NCS_CONNECTED) != ncStausList.end())
{
iReLoadFlag = 0;
}
}

__REINSTALL:

CoUninitialize();

if (false == bIsInstalledNcCard) // 未安装,重新安装
{
// #1 未安装,重新安装
if (false == bIsInstalledNcCard)
{
SP_DEV_LOGW("[NetCard] Detect Nc Card Not Installed");

// #2 重新安装
bIsInstalledNcCard = true;
std::thread installCardThread([] {
g_sp_trust_model->NotifyUpMessage(SP_TRUST_TOPIC_MSG_NC_INSTALL, SPJSONObject(), 100);
});
installCardThread.detach();

// #3 等待客户端安装
Sleep(15 * 1000);
}
}
else
{
Sleep(1 * 1000); // 每一秒检查一次
}

} while (true);

return;
}

网卡是否存在

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

bool IsExistNcCard()
{
bool bIsExist = false;
int nNetCardSize = 20;

std::shared_ptr<IP_ADAPTER_INFO> pIpAdapterInfo(new IP_ADAPTER_INFO[nNetCardSize]);
unsigned long stSize = sizeof(IP_ADAPTER_INFO) * nNetCardSize;
//获取所有网卡信息,参数二为输入输出参数
int nRel = GetAdaptersInfo(pIpAdapterInfo.get(), &stSize);
// 空间不足
if (ERROR_BUFFER_OVERFLOW == nRel) {

pIpAdapterInfo.reset(new IP_ADAPTER_INFO[stSize]);
if (GetAdaptersInfo(pIpAdapterInfo.get(), &stSize) != NO_ERROR)
{
std::cout << "Failed to get adapter info" << std::endl;
return false;
}
}

PIP_ADAPTER_INFO cur = pIpAdapterInfo.get();
// 多个网卡 通过链表形式链接起来的
std::string netdesc;
std::string netip;
while (cur) {

netdesc = cur->Description;
switch (cur->Type) {
case MIB_IF_TYPE_OTHER:
break;
case MIB_IF_TYPE_ETHERNET:
{
IP_ADDR_STRING* pIpAddrString = &(cur->IpAddressList);
netip = pIpAddrString->IpAddress.String;
}
break;
case MIB_IF_TYPE_TOKENRING:
break;
case MIB_IF_TYPE_FDDI:
break;
case MIB_IF_TYPE_PPP:
break;
case MIB_IF_TYPE_LOOPBACK:
break;
case MIB_IF_TYPE_SLIP:
break;
default://无线网卡,Unknown type
{
IP_ADDR_STRING* pIpAddrString = &(cur->IpAddressList);
netip = pIpAddrString->IpAddress.String;
}
break;
}
char hex[16] = { '0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F' };

// mac 地址一般6个字节
// mac 二进制转16进制字符串
char macStr[18] = { 0 };//12+5+1
int k = 0;
for (UINT j = 0; j < cur->AddressLength; j++) {
macStr[k++] = hex[(cur->Address[j] & 0xf0) >> 4];
macStr[k++] = hex[cur->Address[j] & 0x0f];
macStr[k++] = '-';
}

if (k < 18 && k > 0)
{
macStr[k - 1] = 0;
}

cur = cur->Next;

// 找到 "TrustAgent VNIC"
if (netdesc.find("TrustAgent VNIC") != std::string::npos)
{
bIsExist = true;
goto _END_;
}
}

_END_:

return bIsExist;
}

【网络编程】【Windows】获取网卡数量
https://hodlyounger.github.io/A_OS/Windows/网络helper/【网络编程】获取网卡数量/
作者
mingming
发布于
2023年10月27日
许可协议