相关文章: 使用winsock2

说明

监控网卡可以使用 NotifyRouteChangeNotifyRouteChange2 函数,通过注册回调实现路由监控

主要步骤

  1. 声明一个回调函数处理通知
  2. 调用notifyRouteChange2注册通知,指定通知类型
  3. 等待通知
  4. 取消通知(可选)
  5. 在回调函数中根据通知类型进行处理

代码

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
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif

#define _WINSOCK_DEPRECATED_NO_WARNINGS

#include <iostream>
#include<iomanip>
#include<string>
#include <windows.h>
#include <winsock2.h>
#include <ws2tcpip.h>
#include <iphlpapi.h>

#pragma comment(lib, "iphlpapi.lib")
#pragma comment(lib, "ws2_32.lib")

using namespace std;

#define NAMEPRINTFORMAT(X) std::left << setw(60)<< #X << "\t\t" << X

std::string ipToString(DWORD dwIP)
{
std::string strDestIp = "";
std::string strMaskIp = "";

struct in_addr network;
network.S_un.S_addr = dwIP; //为s_addr赋值--网络字节序
strDestIp = inet_ntoa(network);

return strDestIp;
}


void CALLBACK RouteChanged1(void* CallerContext, PMIB_IPFORWARD_ROW2 Table, MIB_NOTIFICATION_TYPE NotificationType)
{
using context = void(*)(DWORD);

context ctx = (context)CallerContext;

auto PrintTable = [](MIB_IPFORWARD_ROW2 table) {
cout << "---------------" << endl;
cout << NAMEPRINTFORMAT(table.InterfaceLuid.Info.IfType) << endl;

cout << NAMEPRINTFORMAT(table.InterfaceLuid.Info.NetLuidIndex) << endl;
cout << NAMEPRINTFORMAT(table.InterfaceLuid.Info.Reserved) << endl;
cout << NAMEPRINTFORMAT(table.InterfaceLuid.Value) << endl;

cout << NAMEPRINTFORMAT(table.InterfaceIndex) << endl;


cout << NAMEPRINTFORMAT(table.DestinationPrefix.Prefix.si_family) << endl;
cout << NAMEPRINTFORMAT(table.DestinationPrefix.Prefix.Ipv4.sin_addr.S_un.S_addr) << "\t" << ipToString(table.DestinationPrefix.Prefix.Ipv4.sin_addr.S_un.S_addr) << endl;
cout << NAMEPRINTFORMAT(table.DestinationPrefix.Prefix.Ipv4.sin_family) << endl;
cout << NAMEPRINTFORMAT(table.DestinationPrefix.Prefix.Ipv4.sin_port) << endl;
cout << NAMEPRINTFORMAT(table.DestinationPrefix.Prefix.Ipv4.sin_zero) << endl;

cout << NAMEPRINTFORMAT(table.DestinationPrefix.Prefix.Ipv6.sin6_addr.u.Byte) << endl;
cout << NAMEPRINTFORMAT(table.DestinationPrefix.Prefix.Ipv6.sin6_addr.u.Word) << endl;
cout << NAMEPRINTFORMAT(table.DestinationPrefix.Prefix.Ipv6.sin6_family) << endl;
cout << NAMEPRINTFORMAT(table.DestinationPrefix.Prefix.Ipv6.sin6_flowinfo) << endl;
cout << NAMEPRINTFORMAT(table.DestinationPrefix.Prefix.Ipv6.sin6_port) << endl;
cout << NAMEPRINTFORMAT(table.DestinationPrefix.Prefix.Ipv6.sin6_scope_id) << endl;
cout << NAMEPRINTFORMAT(table.DestinationPrefix.Prefix.Ipv6.sin6_scope_struct.Level) << endl;
cout << NAMEPRINTFORMAT(table.DestinationPrefix.Prefix.Ipv6.sin6_scope_struct.Value) << endl;
cout << NAMEPRINTFORMAT(table.DestinationPrefix.Prefix.Ipv6.sin6_scope_struct.Zone) << endl;


cout << NAMEPRINTFORMAT(table.NextHop.Ipv4.sin_addr.S_un.S_addr) << "\t" << ipToString(table.NextHop.Ipv4.sin_addr.S_un.S_addr) << endl;
cout << NAMEPRINTFORMAT(table.NextHop.Ipv6.sin6_addr.u.Byte) << endl;
cout << NAMEPRINTFORMAT(table.NextHop.Ipv6.sin6_addr.u.Word) << endl;
cout << NAMEPRINTFORMAT(table.SitePrefixLength) << endl;
cout << NAMEPRINTFORMAT(table.ValidLifetime) << endl;
cout << NAMEPRINTFORMAT(table.PreferredLifetime) << endl;
cout << NAMEPRINTFORMAT(table.Metric) << endl;
cout << NAMEPRINTFORMAT(table.Protocol) << endl;
cout << NAMEPRINTFORMAT(table.Loopback) << endl;
cout << NAMEPRINTFORMAT(table.AutoconfigureAddress) << endl;
cout << NAMEPRINTFORMAT(table.Immortal) << endl;
cout << NAMEPRINTFORMAT(table.Age) << endl;
cout << NAMEPRINTFORMAT(table.Origin) << endl;

cout << "---------------" << endl << endl;
};
// 处理路由表变更通知
switch (NotificationType)
{
case MibParameterNotification:
cout << "1-- 参数被更改" << endl;
break;
case MibAddInstance:
cout << "2-- 添加" << endl;
PrintTable(*Table);

ctx(Table->DestinationPrefix.Prefix.Ipv4.sin_addr.S_un.S_addr);
break;
case MibDeleteInstance:
cout << "3-- 删除" << endl;
PrintTable(*Table);

ctx(Table->DestinationPrefix.Prefix.Ipv4.sin_addr.S_un.S_addr);
break;
case MibInitialNotification:
cout << "4-- 函数已注册" << endl;
break;

default:
break;
}
}


void checkIsMyRoute (DWORD ip)
{
cout << NAMEPRINTFORMAT(ipToString(ip)) << endl;
};

void main()
{
HANDLE hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
HANDLE hNotify = NULL;
PVOID callerContext = static_cast<PVOID>(&checkIsMyRoute);
BOOLEAN bSuccess = TRUE;
ULONG pdwPrevNotified = 0;

if (callerContext != nullptr && NotifyRouteChange2(AF_UNSPEC, &RouteChanged1, callerContext, bSuccess, &hNotify) != NO_ERROR) {
printf("Could not register for route change notifications\n");
return ;
}

while (TRUE) {
DWORD dwWait = WaitForSingleObject(hNotify, INFINITE);
if (dwWait == WAIT_OBJECT_0) {
// 接收到异步通知,处理结果
break;
}
}

// 取消监控
CancelMibChangeNotify2(hNotify);
CloseHandle(hNotify);

return ;
}