WinPcap相关文件地址WinPcap_4_1_3免安装版.zip_winpcap-C++文档类资源-CSDN下载
请先确保下面的x64和x86中的存在
这些是依赖文件,实在找不到,就去这个地址下载吧(64条消息) WinPcap_4_1_3的依赖文件-C++文档类资源-CSDN文库
下面是具体的使用方法
//调用代码的方法,WM_USER+8899这个定时器是用来显示每秒流量是多少 #ifdef USE_WPCAP //创建一个实时监控网速的线程 std::thread netSpeedThread(NetTrafficMonitorThread); netSpeedThread.detach(); SetTimer(GetHWND(), WM_USER + 8899, 1000, NULL); #endif //流量分为上传和下载,这里是WM_USER+8899定时器内的相关代码 if (wParam == WM_USER + 8899) { int nUpValuesTemp = g_nUpValues - g_nOldUpValues; int nDownValuesTemp = g_nDownValues - g_nOldDownValues; if (g_nOldUpValues == 0 || g_nOldDownValues == 0) { g_nOldUpValues = g_nUpValues; g_nOldDownValues = g_nDownValues; bHandled = true; return S_OK; } g_nOldUpValues = g_nUpValues; g_nOldDownValues = g_nDownValues; CStringW strUploadText; if (nUpValuesTemp / (1024 * 1024) >= 1) { strUploadText.Format(_T("%.2fM/s "), nUpValuesTemp / (1024 * 1024.00)); } else { strUploadText.Format(_T("%.2fK/s "), nUpValuesTemp / 1024.00); } CString strDownloadText; if (nDownValuesTemp / (1024 * 1024) >= 1) { strDownloadText.Format(_T("%.2fM/s "), nDownValuesTemp / (1024 * 1024.00)); } else { strDownloadText.Format(_T("%.2fK/s "), nDownValuesTemp / 1024.00); } down_net_label_->SetText(strDownloadText.GetBuffer());//显示下载速度 up_net_label_->SetText(strUploadText.GetBuffer());//显示上传速度 } //下面的具体的NetTrafficMonitorThread线程源码, int g_nUpValues = 0; int g_nDownValues = 0; int g_nOldUpValues = 0; int g_nOldDownValues = 0; bool g_bStartWpcapSuccess = false;//记录是否开启Wpcap成功 string toIp(DWORD ip) { size_t a = ip >> 24 & 0xFF; size_t b = ip >> 16 & 0xFF; size_t c = ip >> 8 & 0xFF; size_t d = ip & 0xFF; // 数据是大端就用 abcd,小端dcba return string(to_string(d) + "." + to_string(c) + "." + to_string(b) + "." + to_string(a)); } //BOOL eachTCP(DWORD pid, vector* connectNets) //{ // PMIB_TCPTABLE2 pTcpTable = nullptr; // ULONG ulSize = 0; // DWORD dwRetVal = 0; // // // 第一次获取大小,初始化pTcpTable // if ((dwRetVal = GetTcpTable2(pTcpTable, &ulSize, TRUE)) == // ERROR_INSUFFICIENT_BUFFER) { // pTcpTable = (MIB_TCPTABLE2*)MALLOC(ulSize); // if (pTcpTable == NULL) return 0; // } // // // 第二次获取数据 // if ((dwRetVal = GetTcpTable2(pTcpTable, &ulSize, TRUE)) == NO_ERROR) { // if (pTcpTable == NULL) return 0; // // for (size_t i = 0; i < pTcpTable->dwNumEntries; i++) { // auto it = pTcpTable->table[i]; // if (pid != it.dwOwningPid && pid != 0) continue; // string state = ""; // switch (it.dwState) { // case MIB_TCP_STATE_CLOSED: // state = "CLOSED"; // break; // case MIB_TCP_STATE_LISTEN: // state = "LISTEN"; // break; // case MIB_TCP_STATE_SYN_SENT: // state = ("SYN-SENT"); // break; // case MIB_TCP_STATE_SYN_RCVD: // state = ("SYN-RECEIVED"); // break; // case MIB_TCP_STATE_ESTAB: // state = ("ESTABLISHED"); // break; // case MIB_TCP_STATE_FIN_WAIT1: // state = ("FIN-WAIT-1"); // break; // case MIB_TCP_STATE_FIN_WAIT2: // state = ("FIN-WAIT-2"); // break; // case MIB_TCP_STATE_CLOSE_WAIT: // state = ("CLOSE-WAIT"); // break; // case MIB_TCP_STATE_CLOSING: // state = ("CLOSING"); // break; // case MIB_TCP_STATE_LAST_ACK: // state = ("LAST-ACK"); // break; // case MIB_TCP_STATE_TIME_WAIT: // state = ("TIME-WAIT"); // break; // case MIB_TCP_STATE_DELETE_TCB: // state = ("DELETE-TCB"); // break; // default: // state = ("UNKNOWN dwState value"); // break; // } // // ConnectNet net; // net.proto = 6; // net.src = toIp(it.dwLocalAddr); // net.sport = ntohs((u_short)it.dwLocalPort); // net.dst = toIp(it.dwRemoteAddr); // net.dport = ntohs((u_short)it.dwRemotePort); // net.state = state; // net.pid = it.dwOwningPid; // connectNets->push_back(net); // } // } // else { // FREE(pTcpTable); // return FALSE; // } // // if (pTcpTable != NULL) { // FREE(pTcpTable); // pTcpTable = NULL; // } // return TRUE; //} BOOL eachUDP(DWORD pid, vector * connectNets) { MIB_UDPTABLE_OWNER_PID* pUdpTable = nullptr; ULONG ulSize = 0; DWORD dwRetVal = 0; // 第一次获取大小,初始化pTcpTable if ((dwRetVal = GetExtendedUdpTable(pUdpTable, &ulSize, TRUE, AF_INET, UDP_TABLE_CLASS::UDP_TABLE_OWNER_PID, 0)) == ERROR_INSUFFICIENT_BUFFER) { pUdpTable = (MIB_UDPTABLE_OWNER_PID*)MALLOC(ulSize); if (pUdpTable == NULL) return 0; } // 第二次获取数据 if ((dwRetVal = GetExtendedUdpTable(pUdpTable, &ulSize, TRUE, AF_INET, UDP_TABLE_CLASS::UDP_TABLE_OWNER_PID, 0)) == NO_ERROR) { if (pUdpTable == NULL) return 0; for (size_t i = 0; i < pUdpTable->dwNumEntries; i++) { auto it = pUdpTable->table[i]; if (it.dwOwningPid != pid && pid != 0) continue; ConnectNet net; net.proto = 17; net.src = toIp(it.dwLocalAddr).c_str(); net.sport = ntohs((u_short)it.dwLocalPort); net.dst = "*"; net.dport = 0; net.state = ""; net.pid = it.dwOwningPid; connectNets->push_back(net); } } else { FREE(pUdpTable); return FALSE; } if (pUdpTable != NULL) { FREE(pUdpTable); pUdpTable = NULL; } return TRUE; } BOOL getNetTable(DWORD pid, vector * connectNets) { //if (!eachTCP(pid, connectNets)) return FALSE; return eachUDP(pid, connectNets); } map m_mapNetPortInfo; //int表示本地端口 int m_nTryGetUdpTimes = 0;//获取udp端口次数 void packet_handler(u_char *param, const struct pcap_pkthdr *header, const u_char *pkt_data) { #ifdef USE_WPCAP struct tm *ltime; ip_header *ih; udp_header *uh; u_int ip_len; u_short sport, dport; time_t local_tv_sec; (VOID)(param); local_tv_sec = header->ts.tv_sec; ltime = localtime(&local_tv_sec); char timestr[16]; strftime(timestr, sizeof timestr, "%H:%M:%S", ltime); //printf("%s.%.6d len:%d ", timestr, header->ts.tv_usec, header->len); ih = (ip_header *)(pkt_data + 14); //length of ethernet header ip_len = (ih->ver_ihl & 0xf) * 4; uh = (udp_header *)((u_char*)ih + ip_len); sport = ntohs(uh->sport); dport = ntohs(uh->dport); //判断是否是爱加进程的UDP端口 if (m_mapNetPortInfo.size() <= 1 && m_nTryGetUdpTimes <= 10) { Sleep(500); m_mapNetPortInfo.clear(); vector r; if (getNetTable(0, &r)) { gLocker.Lock(); for (auto it : r) { if (it.proto == 17 && it.pid == g_nMainProcess) { m_mapNetPortInfo[it.sport] = g_nMainProcess; WriteNormalLog(L"本次视频通信的UDP端口为:" + to_wstring(it.sport)); } } gLocker.Unlock(); } if (m_mapNetPortInfo.size() > 2) { WriteNormalLog(L"获取UDP端口时得到" + to_wstring(m_mapNetPortInfo.size()) + L"个, 将清空重新获取!当前获取次数为" + to_wstring(m_nTryGetUdpTimes)); if (m_nTryGetUdpTimes < 10) m_mapNetPortInfo.clear(); else { wstring strLog = L"本次视频获取UDP端口结束! 当前监视的端口为"; for (auto itor : m_mapNetPortInfo) strLog += to_wstring(itor.first) + L", "; WriteNormalLog(strLog); } } else if (m_mapNetPortInfo.size() == 2) { wstring strLog = L"--------本次视频通信的UDP端口为:"; for (auto itor : m_mapNetPortInfo) { strLog += to_wstring(itor.first) + L", "; } WriteNormalLog(strLog); } m_nTryGetUdpTimes++; } gLocker.Lock(); for (auto itor : m_mapNetPortInfo) { if (sport == itor.first || dport == itor.first) { if (sport == itor.first) { g_nUpValues += (header->len - 20); } else g_nDownValues += header->len - 20;//这里减20是ip信息头 } } gLocker.Unlock(); #endif } MIB_IFTABLE* m_pIfTable; int m_connection_selected = 0; string m_connection_name; vector m_connections; //保存获取到的所有网络连接 pcap_t* m_Pcap_t; void AutoSelect() { unsigned int max_in_out_bytes{}; unsigned int in_out_bytes; //m_connection_selected = m_connections[0].index; m_connection_selected = 0; //自动选择连接时,查找已发送和已接收字节数之和最多的那个连接,并将其设置为当前查看的连接 for (size_t i{}; i table[m_connections[i].index].dwOperStatus == IF_OPER_STATUS_OPERATIONAL) //只选择网络状态为正常的连接 { in_out_bytes = m_pIfTable->table[m_connections[i].index].dwInOctets + m_pIfTable->table[m_connections[i].index].dwOutOctets; if (in_out_bytes > max_in_out_bytes) { max_in_out_bytes = in_out_bytes; m_connection_selected = i; } } } m_connection_name = m_connections[m_connection_selected].adapterName; } void IniConnection() { //为m_pIfTable开辟所需大小的内存 free(m_pIfTable); DWORD m_dwSize = sizeof(MIB_IFTABLE); m_pIfTable = (MIB_IFTABLE *)malloc(m_dwSize); int rtn; rtn = GetIfTable(m_pIfTable, &m_dwSize, FALSE); if (rtn == ERROR_INSUFFICIENT_BUFFER) //如果函数返回值为ERROR_INSUFFICIENT_BUFFER,说明m_pIfTable的大小不够 { free(m_pIfTable); m_pIfTable = (MIB_IFTABLE *)malloc(m_dwSize); //用新的大小重新开辟一块内存 } //获取当前所有的连接,并保存到m_connections容器中 GetIfTable(m_pIfTable, &m_dwSize, FALSE); //获取当前所有的连接,并保存到m_connections容器中 CAdapterCommon::GetAdapterInfo(m_connections); CAdapterCommon::GetIfTableInfo(m_connections, m_pIfTable); //选择网络连接 AutoSelect(); } static bool IsWin64(void) { SYSTEM_INFO si = { 0 }; typedef void (WINAPI *LPFN_PGNSI)(LPSYSTEM_INFO); LPFN_PGNSI pGNSI = (LPFN_PGNSI)GetProcAddress(GetModuleHandleA(("kernel32.dll")), "GetNativeSystemInfo"); if (pGNSI) pGNSI(&si); if (si.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64) { return true; } return false; } void NetTrafficMonitorThread() { g_bStartWpcapSuccess = false; m_mapNetPortInfo.clear(); m_nTryGetUdpTimes = 0; #ifdef USE_WPCAP pcap_if_t *alldevs; char errbuf[PCAP_ERRBUF_SIZE]; u_int netmask; char packet_filter[] = "ip and udp"; struct bpf_program fcode; //判断system32下是否有wpcap.dll和packet.dll, system32drivers下是否有npf.sys //如果电脑是64位,则同时还需要判断SysWOW64下是否有wpcap.dll和packet.dll wchar_t path_x86[256] = { 0 }; wchar_t path_x64[256] = { 0 }; if (IsWin64()) { WriteNormalLog(L"64位系统!"); typedef BOOL(APIENTRY *PWow64EnableWow64FsRedirection)(BOOL); PWow64EnableWow64FsRedirection pf = (PWow64EnableWow64FsRedirection)GetProcAddress(GetModuleHandleW(L"kernel32.dll"), "Wow64EnableWow64FsRedirection"); //移动64位的wpcap.dll和packet.dll到system32下,移动npf.sys到system32drivers下 wstring strWpcapDllPath64 = bc::Path::GetAppPath() + L"WinPcap\x64\wpcap.dll"; wstring strPacketDllPath64 = bc::Path::GetAppPath() + L"WinPcap\x64\packet.dll"; if (_waccess(strWpcapDllPath64.c_str(), 0) != -1 && _waccess(strPacketDllPath64.c_str(), 0) != -1) { SHGetSpecialFolderPath( NULL, // 保留 path_x64, // 接受文件路径的字符串指针 CSIDL_SYSTEM, // CSIDL 宏 FALSE // 如果文件夹不存在,则不创建文件夹 ); wstring strWpcapDll = (wstring)path_x64 + L"\wpcap.dll"; wstring strPacketDll = (wstring)path_x64 + L"\packet.dll"; if (_waccess(strWpcapDll.c_str(), 0) == -1) { //关闭重定向 if (pf(FALSE))//关闭重定向 { BOOL bRet = CopyFile(strWpcapDllPath64.c_str(), strWpcapDll.c_str(), TRUE); pf(TRUE);//恢复重定向 if (!bRet) { WriteErrorLog(L"复制wpcap.dll失败!GetLastError=" + to_wstring(GetLastError())); return; } } } if (_waccess(strPacketDll.c_str(), 0) == -1) { if (pf(FALSE))//关闭重定向 { BOOL bRet = CopyFile(strPacketDllPath64.c_str(), strPacketDll.c_str(), TRUE); pf(TRUE);//恢复重定向 if (!bRet) { WriteErrorLog(L"复制packet.dll失败!GetLastError=" + to_wstring(GetLastError())); return; } } } //移动npf.sys到system32drivers下 wstring strNpfPath = bc::Path::GetAppPath() + L"WinPcap\x64\npf.sys"; if (_waccess(strNpfPath.c_str(), 0) != -1) { wstring strNpf = (wstring)path_x64 + L"\drivers\npf.sys"; if (_waccess(strNpf.c_str(), 0) == -1) { if (pf(FALSE))//关闭重定向 { BOOL bRet = CopyFile(strNpfPath.c_str(), strNpf.c_str(), TRUE); pf(TRUE);//恢复重定向 if (!bRet) { int nError = GetLastError(); if (nError != 0 && nError != 80) WriteErrorLog(L"复制npf.sys失败!GetLastError=" + to_wstring(nError)); //return; } } } } } //移动32位的wpcap.dll和packet.dll到SysWOW64下 wstring strWpcapDllPath32 = bc::Path::GetAppPath() + L"WinPcap\x86\wpcap.dll"; wstring strPacketDllPath32 = bc::Path::GetAppPath() + L"WinPcap\x86\packet.dll"; if (_waccess(strWpcapDllPath32.c_str(), 0) != -1 && _waccess(strPacketDllPath32.c_str(), 0) != -1) { SHGetSpecialFolderPath(NULL, // 保留 path_x86, // 接受文件路径的字符串指针 CSIDL_SYSTEMX86, // CSIDL 宏 FALSE // 如果文件夹不存在,则不创建文件夹 ); wstring strWpcapDll = (wstring)path_x86 + L"\wpcap.dll"; wstring strPacketDll = (wstring)path_x86 + L"\packet.dll"; if (_waccess(strWpcapDll.c_str(), 0) == -1) { BOOL bRet = CopyFile(strWpcapDllPath32.c_str(), strWpcapDll.c_str(), TRUE); if (!bRet) { WriteErrorLog(L"复制wpcap.dll失败!GetLastError=" + to_wstring(GetLastError())); return; } } if (_waccess(strPacketDll.c_str(), 0) == -1) { BOOL bRet = CopyFile(strPacketDllPath32.c_str(), strPacketDll.c_str(), TRUE); if (!bRet) { WriteErrorLog(L"复制packet.dll失败!GetLastError=" + to_wstring(GetLastError())); return; } } } } else { WriteNormalLog(L"32位系统!"); //移动32位的wpcap.dll和packet.dll到system32下,移动npf.sys到system32drivers下 wstring strWpcapDllPath32 = bc::Path::GetAppPath() + L"WinPcap\x86\wpcap.dll"; wstring strPacketDllPath32 = bc::Path::GetAppPath() + L"WinPcap\x86\packet.dll"; if (_waccess(strWpcapDllPath32.c_str(), 0) != -1 && _waccess(strPacketDllPath32.c_str(), 0) != -1) { SHGetSpecialFolderPath(NULL, // 保留 path_x86, // 接受文件路径的字符串指针 CSIDL_SYSTEMX86, // CSIDL 宏 FALSE // 如果文件夹不存在,则不创建文件夹 ); wstring strWpcapDll = (wstring)path_x86 + L"\wpcap.dll"; wstring strPacketDll = (wstring)path_x86 + L"\packet.dll"; if (_waccess(strWpcapDll.c_str(), 0) == -1) { BOOL bRet = CopyFile(strWpcapDllPath32.c_str(), strWpcapDll.c_str(), TRUE); if (!bRet) { WriteErrorLog(L"复制wpcap.dll失败!GetLastError=" + to_wstring(GetLastError())); return; } } //移动npf.sys到system32drivers下 wstring strNpfPath = bc::Path::GetAppPath() + L"WinPcap\x86\npf.sys"; if (_waccess(strNpfPath.c_str(), 0) != -1) { wstring strNpf = (wstring)path_x86 + L"\drivers\npf.sys"; if (_waccess(strNpf.c_str(), 0) == -1) { BOOL bRet = CopyFile(strNpfPath.c_str(), strNpf.c_str(), TRUE); if (!bRet) { WriteErrorLog(L"复制npf.sys失败!GetLastError=" + to_wstring(GetLastError())); return; } } } if (_waccess(strPacketDll.c_str(), 0) == -1) { BOOL bRet = CopyFile(strPacketDllPath32.c_str(), strPacketDll.c_str(), TRUE); if (!bRet) { WriteErrorLog(L"复制packet.dll失败!GetLastError=" + to_wstring(GetLastError())); return; } } } } wstring strNpfPath = bc::Path::GetAppPath() + L"WinPcap\"; if (_waccess(strNpfPath.c_str(), 0) == -1) { return; } //判断对应文件夹下是否已存在对应的wpcap.dll和packet.dll以及npf.sys文件 if (IsWin64()) { typedef BOOL(APIENTRY *PWow64EnableWow64FsRedirection)(BOOL); PWow64EnableWow64FsRedirection pf = (PWow64EnableWow64FsRedirection)GetProcAddress(GetModuleHandleW(L"kernel32.dll"), "Wow64EnableWow64FsRedirection"); if (pf(FALSE))//关闭重定向 { wstring strNpf_x64 = (wstring)path_x64 + L"\drivers\npf.sys"; wstring strWpcapDll_x64 = (wstring)path_x64 + L"\wpcap.dll"; wstring strPacketDll_x64 = (wstring)path_x64 + L"\packet.dll"; wstring strWpcapDll_x86 = (wstring)path_x86 + L"\wpcap.dll"; wstring strPacketDll_x86 = (wstring)path_x86 + L"\packet.dll"; if (_waccess(strNpf_x64.c_str(), 0) == -1 || _waccess(strWpcapDll_x64.c_str(), 0) == -1 || _waccess(strPacketDll_x64.c_str(), 0) == -1 || _waccess(strWpcapDll_x86.c_str(), 0) == -1 || _waccess(strPacketDll_x86.c_str(), 0) == -1) { WriteErrorLog(L"64位系统下,wpcap.dll、packet.dll或npf.sys中有文件不存在!GetLastError=" + to_wstring(GetLastError())); pf(TRUE);//恢复重定向 return; } pf(TRUE);//恢复重定向 } } else { wstring strNpf_x86 = (wstring)path_x86 + L"\drivers\npf.sys"; wstring strWpcapDll_x86 = (wstring)path_x86 + L"\wpcap.dll"; wstring strPacketDll_x86 = (wstring)path_x86 + L"\packet.dll"; if (_waccess(strNpf_x86.c_str(), 0) == -1 || _waccess(strWpcapDll_x86.c_str(), 0) == -1 || _waccess(strPacketDll_x86.c_str(), 0) == -1) { WriteErrorLog(L"32位系统下,wpcap.dll、packet.dll或npf.sys中有文件不存在!GetLastError=" + to_wstring(GetLastError())); return; } } //列出当前所有可用的网络设备(网卡) if (pcap_findalldevs(&alldevs, errbuf) == -1) { char buffer[1024] = { 0 }; sprintf_s(buffer, 1024, "Error in pcap_findalldevs: %s!", errbuf); WriteErrorLog(ToWchar(buffer)); return; } //打印所有网络设备(网卡) pcap_if_t *d; int i = 0; map _mapNetInfo; for (d = alldevs; d; d = d->next) { ++i; _mapNetInfo[i] = d->name; wstring strLog = to_wstring(i) + L" " + ToWchar(d->name) + L" "; if (d->description) strLog += ToWchar(d->description); else strLog += L"(No description available)"; WriteNormalLog(strLog); } if (i == 0) { WriteErrorLog(L"No interfaces found! Make sure WinPcap is installed."); return; } int inum = 0; if (i == 1) inum = 1; else { //自动选择网卡(查找已发送和已接收字节数之和最多的那个连接,并将其设置为当前查看的连接) IniConnection(); for (auto it : _mapNetInfo) { int nPos = it.second.find(m_connection_name); if (nPos != string::npos) { inum = it.first; break; } } } if (inum < 1 || inum > i) { WriteErrorLog(L"Adapter number out of range."); pcap_freealldevs(alldevs); return; } for (d = alldevs, i = 0; i< inum - 1; d = d->next, i++); //获取一个包捕捉句柄,类似文件 *** 作函数使用的文件句柄 if ((m_Pcap_t = pcap_open_live(d->name, // name of the device 65536, // portion of the packet to capture. 65536 grants that the whole packet will be captured on all the MACs. 1, // promiscuous mode (nonzero means promiscuous) 1000, // read timeout errbuf // error buffer )) == NULL) { char buffer[1024] = { 0 }; sprintf_s(buffer, 1024, "Unable to open the adapter. %s is not supported by WinPcap!", errbuf); WriteErrorLog(ToWchar(buffer)); pcap_freealldevs(alldevs); return; } if (pcap_datalink(m_Pcap_t) != DLT_EN10MB) { WriteErrorLog(L"This program works only on Ethernet networks."); pcap_freealldevs(alldevs); return; } if (d->addresses != NULL) netmask = ((struct sockaddr_in *)(d->addresses->netmask))->sin_addr.S_un.S_addr; else netmask = 0xffffff; //该函数用于解析过滤规则串 if (pcap_compile(m_Pcap_t, &fcode, packet_filter, 1, netmask) <0) { WriteErrorLog(L"Unable to compile the packet filter. Check the syntax."); pcap_freealldevs(alldevs); return; } //在捕获过程中绑定一个过滤器 if (pcap_setfilter(m_Pcap_t, &fcode)<0) { WriteErrorLog(L"Error setting the filter."); pcap_freealldevs(alldevs); return; } pcap_freealldevs(alldevs); g_bStartWpcapSuccess = true; pcap_loop(m_Pcap_t, 0, packet_handler, NULL); #endif } void EndNetLoopThread() { #ifdef USE_WPCAP if (m_Pcap_t != nullptr) { pcap_breakloop(m_Pcap_t); pcap_close(m_Pcap_t); m_Pcap_t = nullptr; } WriteNormalLog(L"结束UDP端口监听!"); #endif m_mapNetPortInfo.clear(); m_nTryGetUdpTimes = 0; g_nUpValues = 0; g_nDownValues = 0; g_nOldUpValues = 0; g_nOldDownValues = 0; }
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)