[英]How to monitor process network usage under windows
我正在寻找一种方法来获取信息列表作为Windows下的资源监视器,如: 我想知道所选应用程序的地址和发送和接收使用情况。
一开始我正在寻找一个c ++ win32 api或其他开源库来做到这一点,我可以找到像GetProcessInformation这样的东西,但它不包括网络信息。
我看到了一些类似的话题,但他们没有帮助。
Ref_001 ,似乎网络监视器api无法做专用的监视器。
Ref_002 ,我不确定OpenTrace/ProcessTrace/StopTrace
可以让我获得网络使用,而且我也不确定如何使用它。
Ref_003 ,他们建议使用一些工具,但这不是我想要的。
Windows通过两个部分为您提供这些信息,这些部分来自不同的功能,您需要将它们组合在一起以获得完整的故事。 从技术上讲,它有三个功能:对于数据的第二部分,IPv4和IPv6数据有单独的功能。
第一个函数是GetExtendedTcpTable 。 要获取上述所有信息,您可能需要调用此(至少)两次:一次使用TCP_TABLE_OWNER_PID_CONNECTIONS
标志,一次使用TCP_TABLE_OWNER_MODULE_CONNECTIONS
标志来检索PID和本地可执行文件的模块名称。
第二对可以获取有关特定连接上发送/接收的数据的统计信息。 每个连接由本地地址/端口和远程地址端口的组合标识(与上面使用的相同)。 使用GetPerTcpConnectionEStats for IPv4或GetPerTcp6ConnectionEStats for IPv6检索信息。
其中任何一个都将检索一个表,表中的每一行都包含一个连接的统计信息。 如果您(例如)在浏览器中打开了多个选项卡,则可以选择单独显示每个连接的数据,也可以按照您认为合适的方式将它们合并。
感谢您的指导Jerry Coffin
这是我从这些库中获得的一些非常“POC”的代码。 Spoiler alert - 刚刚在这里实现了TCPv4。 代码引自
https://docs.microsoft.com/en-gb/windows/desktop/api/iphlpapi/nf-iphlpapi-getpertcpconnectionestats
请原谅hacky代码的性质,但我认为发布比等待那个永远不会到来的完美日子更好!
容器“NetworkPerformanceItem.h”的结果容器
#pragma once
#include "stdafx.h"
#include <string>
#include <windows.h>
class NetworkPerformanceItem
{
public:
NetworkPerformanceItem();
~NetworkPerformanceItem();
INT ProcessId;
INT State;
std::string LocalAddress;
std::string RemoteAddress;
int LocalPort;
int RemotePort;
LONG BytesOut;
LONG BytesIn;
LONG OutboundBandwidth;
LONG InboundBandwidth;
int Pass = 0;
std::string CollectionTime;
};
标题“NetworkPerformanceScanner.h”
#pragma once
#include <iostream>
#include <vector>
#include <sstream>
#include "NetworkPerformanceItem.h"
#include <iomanip>
#include <iostream>
#include <windows.h>
#include <winsock2.h>
#include <Ws2tcpip.h>
#include <iphlpapi.h>
#include <Tcpestats.h>
#include <stdlib.h>
#include <stdio.h>
using namespace std;
#pragma comment(lib, "iphlpapi.lib")
#pragma comment(lib, "ws2_32.lib")
#define MALLOC(x) HeapAlloc(GetProcessHeap(), 0, (x))
#define FREE(x) HeapFree(GetProcessHeap(), 0, (x))
class NetworkPerformanceScanner
{
public:
NetworkPerformanceScanner();
~NetworkPerformanceScanner();
std::vector<NetworkPerformanceItem> ScanNetworkPerformance(int sampleId);
};
来源“NetworkPerformanceScanner.cpp”
#include "stdafx.h"
#include "NetworkPerformanceScanner.h"
NetworkPerformanceScanner::NetworkPerformanceScanner()
{
}
NetworkPerformanceScanner::~NetworkPerformanceScanner()
{
}
// TODO - implement TCP v6, UDP
std::vector<NetworkPerformanceItem> NetworkPerformanceScanner::ScanNetworkPerformance(int pass)
{
std::vector<unsigned char> buffer;
DWORD dwSize = sizeof(MIB_TCPTABLE_OWNER_PID);
DWORD dwRetValue = 0;
vector<NetworkPerformanceItem> networkPerformanceItems;
// get local computer time with timezone offset
auto time = std::time(nullptr);
std::ostringstream timeStream;
timeStream << std::put_time(std::localtime(&time), "%F %T%z");
string collectionTime = timeStream.str();
// repeat till buffer is big enough
do
{
buffer.resize(dwSize, 0);
dwRetValue = GetExtendedTcpTable(buffer.data(), &dwSize, TRUE, AF_INET, TCP_TABLE_OWNER_PID_ALL, 0);
} while (dwRetValue == ERROR_INSUFFICIENT_BUFFER);
if (dwRetValue == ERROR_SUCCESS)
{
// good case
// cast to access element values
PMIB_TCPTABLE_OWNER_PID ptTable = reinterpret_cast<PMIB_TCPTABLE_OWNER_PID>(buffer.data());
cout << "Number of Entries: " << ptTable->dwNumEntries << endl << endl;
// caution: array starts with index 0, count starts by 1
for (DWORD i = 0; i < ptTable->dwNumEntries; i++)
{
NetworkPerformanceItem networkPerformanceItem;
networkPerformanceItem.ProcessId = ptTable->table[i].dwOwningPid;
networkPerformanceItem.State = ptTable->table[i].dwState;
cout << "PID: " << ptTable->table[i].dwOwningPid << endl;
cout << "State: " << ptTable->table[i].dwState << endl;
std::ostringstream localStream;
localStream << (ptTable->table[i].dwLocalAddr & 0xFF)
<< "."
<< ((ptTable->table[i].dwLocalAddr >> 8) & 0xFF)
<< "."
<< ((ptTable->table[i].dwLocalAddr >> 16) & 0xFF)
<< "."
<< ((ptTable->table[i].dwLocalAddr >> 24) & 0xFF)
<< ":"
<< htons((unsigned short)ptTable->table[i].dwLocalPort);
networkPerformanceItem.LocalAddress = localStream.str();
networkPerformanceItem.LocalPort = ptTable->table[i].dwLocalPort;
std::ostringstream remoteStream;
remoteStream << (ptTable->table[i].dwRemoteAddr & 0xFF)
<< "."
<< ((ptTable->table[i].dwRemoteAddr >> 8) & 0xFF)
<< "."
<< ((ptTable->table[i].dwRemoteAddr >> 16) & 0xFF)
<< "."
<< ((ptTable->table[i].dwRemoteAddr >> 24) & 0xFF)
<< ":"
<< htons((unsigned short)ptTable->table[i].dwRemotePort);
networkPerformanceItem.RemoteAddress = remoteStream.str();
networkPerformanceItem.RemotePort = ptTable->table[i].dwRemotePort;
MIB_TCPROW row;
row.dwLocalAddr = ptTable->table[i].dwLocalAddr;
row.dwLocalPort = ptTable->table[i].dwLocalPort;
row.dwRemoteAddr = ptTable->table[i].dwRemoteAddr;
row.dwRemotePort = ptTable->table[i].dwRemotePort;
row.dwState = ptTable->table[i].dwState;
void *processRow = &row;
if (row.dwRemoteAddr != 0)
{
ULONG rosSize = 0, rodSize = 0;
ULONG winStatus;
PUCHAR ros = NULL, rod = NULL;
rodSize = sizeof(TCP_ESTATS_DATA_ROD_v0);
PTCP_ESTATS_DATA_ROD_v0 dataRod = { 0 };
if (rosSize != 0) {
ros = (PUCHAR)malloc(rosSize);
if (ros == NULL) {
wprintf(L"\nOut of memory");
return networkPerformanceItems;
}
else
memset(ros, 0, rosSize); // zero the buffer
}
if (rodSize != 0) {
rod = (PUCHAR)malloc(rodSize);
if (rod == NULL) {
free(ros);
wprintf(L"\nOut of memory");
return networkPerformanceItems;
}
else
memset(rod, 0, rodSize); // zero the buffer
}
winStatus = GetPerTcpConnectionEStats((PMIB_TCPROW)&row, TcpConnectionEstatsData, NULL, 0, 0, ros, 0, rosSize, rod, 0, rodSize);
dataRod = (PTCP_ESTATS_DATA_ROD_v0)rod;
networkPerformanceItem.BytesIn = dataRod->DataBytesIn;
networkPerformanceItem.BytesOut = dataRod->DataBytesOut;
PTCP_ESTATS_BANDWIDTH_ROD_v0 bandwidthRod = { 0 };
rodSize = sizeof(TCP_ESTATS_BANDWIDTH_ROD_v0);
if (rodSize != 0) {
rod = (PUCHAR)malloc(rodSize);
if (rod == NULL) {
free(ros);
wprintf(L"\nOut of memory");
return networkPerformanceItems;
}
else
memset(rod, 0, rodSize); // zero the buffer
}
winStatus = GetPerTcpConnectionEStats((PMIB_TCPROW)&row,TcpConnectionEstatsBandwidth, NULL, 0, 0, ros, 0, rosSize, rod, 0, rodSize);
bandwidthRod = (PTCP_ESTATS_BANDWIDTH_ROD_v0)rod;
networkPerformanceItem.OutboundBandwidth = bandwidthRod->OutboundBandwidth;
networkPerformanceItem.InboundBandwidth = bandwidthRod->InboundBandwidth;
}
networkPerformanceItem.Pass = pass;
networkPerformanceItem.CollectionTime = collectionTime;
networkPerformanceItems.push_back(networkPerformanceItem);
}
}
else
{
// bad case, do some sh*t here
}
return networkPerformanceItems;
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.