windows获取进程流量
铺垫
获取进程使用的端口
http://blog.csdn.net/rongxiaojun1989/article/details/42417767
抓包
http://blog.csdn.net/rongxiaojun1989/article/details/42744761
IP数据包格式
http://blog.csdn.net/rongxiaojun1989/article/details/42743503
概要方案
1. 获取进程此刻使用的端口号
2. 网卡抓包
3. 流量累积
4. 计算结果
详细方案
1. 获取进程此刻使用的端口号
2. 在各个网卡抓包
3. 拆包解析,查看四元组
4. 流量累计
5. 流量累计结果与所用时间的比值即为结果
附加知识
经验证,非阻塞recv抓包30w约等于1s,视电脑处理速度而定。
实现代码
bool GetProcNetworkFlow(const std::string &sNameProc, double &dbpsRecv, double &dbpsSend)
{
/*获取进程Port*/
std::set<DWORD> setPort;
if(!GetProcessPort(sNameProc, setPort))
{
printf("GetProcessPort == false, sNameProc=%s\n", sNameProc.c_str());
return false;
}
/*获取所有网卡IP*/
std::vector<std::string> vecHostIp;
if(!GetLocalHostIp(vecHostIp))
{
printf("GetLocalHostIp == false\n");
return false;
}
/*遍历网卡*/
for(size_t i = 0; i != vecHostIp.size(); ++i)
{
/*创建RAW socket*/
SOCKET s = socket(AF_INET, SOCK_RAW, IPPROTO_IP);
if(INVALID_SOCKET == s)
{
printf("socket == INVALID_SOCKET, ErrorCode=%d\n", GetLastError());
return false;
}
/*设置非阻塞*/
DWORD dwCmdParam = 1;
if(SOCKET_ERROR == ioctlsocket(s, FIONBIO, &dwCmdParam))
{
printf("ioctlsocket(s, FIONBIO, &dwCmdParam) == SOCKET_ERROR, ErrorCode=%d\n", GetLastError());
return false;
}
/*初始化sockaddr*/
sockaddr_in addr;
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = inet_addr(vecHostIp[i].c_str());
addr.sin_port = htons(4444);
/*绑定网卡地址*/
if(SOCKET_ERROR == bind(s, (sockaddr*)&addr, sizeof(addr)))
{
printf("bind == SOCKET_ERROR, ErrorCode=%d\n", GetLastError());
return 0;
}
/*设置socket模式*/
RCVALL_VALUE emRcvallValue = RCVALL_IPLEVEL;
DWORD dwBytesReturned = 0;
if(SOCKET_ERROR == WSAIoctl(s, SIO_RCVALL, &emRcvallValue,
sizeof(emRcvallValue), NULL, 0, &dwBytesReturned, NULL, NULL))
{
printf("WSAIoctl == SOCKET_ERROR, ErrorCode=%d\n", GetLastError());
return false;
}
/*设置计时器*/
LARGE_INTEGER liTimeStart, liTimeEnd, liTimeElapse;
LARGE_INTEGER liFrequency;
QueryPerformanceFrequency(&liFrequency);
QueryPerformanceCounter(&liTimeStart);
/*抓包*/
int iBytesRecv = 0, iBytesSend = 0;
char cBuffer[100*1024] = {0};
for(int k = 0; k != 300000; ++k)
{
int iLenRecv = recv(s, cBuffer, 100*1024, 0);
if(SOCKET_ERROR == iLenRecv)
{
if(WSAEWOULDBLOCK == GetLastError())
continue;
printf("recv == SOCKET_ERROR, ErrorCode=%d\n", GetLastError());
break;
}
if(0 == iLenRecv)
{
printf("recv == SOCKET_ERROR, Connection Closed\n");
break;
}
cBuffer[iLenRecv] = '\0';
/*验证IP协议版本*/
int iVersionIp = static_cast<unsigned char>(cBuffer[0]) >> 4;
if(iVersionIp != 4)
continue;
/*验证协议*/
int iProto = static_cast<unsigned char>(cBuffer[9]);
if(iProto != 6 && iProto != 17)
continue;
/*取IP头长度*/
int iLenIpHeader = cBuffer[0] & 0x0F;
iLenIpHeader *= 4;
/*获取Ip*/
std::string sIpSrc, sIpDest;
for(int m = 0; m != 4; ++m)
{
sIpSrc += std::to_string(static_cast<ULONGLONG>(static_cast<unsigned char>(cBuffer[12+m])));
sIpDest += std::to_string(static_cast<ULONGLONG>(static_cast<unsigned char>(cBuffer[16+m])));
if(m != 3)
{
sIpSrc += ".";
sIpDest += ".";
}
}
/*判断传输方向*/
bool bRecv;
if(std::find(vecHostIp.begin(), vecHostIp.end(), sIpDest) != vecHostIp.end())
bRecv = true;
else if(std::find(vecHostIp.begin(), vecHostIp.end(), sIpSrc) != vecHostIp.end())
bRecv = false;
else
continue;
/*获取Port*/
int iPortSrc = 0, iPortDest = 0;
memcpy(&iPortSrc, &cBuffer[iLenIpHeader], 2);
memcpy(&iPortDest, &cBuffer[iLenIpHeader+2], 2);
iPortSrc = ntohs(iPortSrc);
iPortDest = ntohs(iPortDest);
/*获取本地端口*/
int iPortLocal = 0;
if(bRecv)
iPortLocal = iPortDest;
else
iPortLocal = iPortSrc;
/*验证Port*/
if(setPort.find(iPortLocal) == setPort.end())
continue;
/*获取IP总长*/
int iLenIp = 0;
memcpy(&iLenIp, &cBuffer[2], 2);
iLenIp = ntohs(iLenIp);
/*取实际数据长*/
int iLenData = 0;
if(iProto == 6)
{
int iLenTcpHeader = static_cast<unsigned char>(cBuffer[iLenIpHeader+12]) >> 4;
iLenTcpHeader *= 4;
iLenData = iLenIp - iLenIpHeader - iLenTcpHeader;
}
else
{
iLenData = iLenIp - iLenIpHeader - 20;
}
/*流量累加*/
if(bRecv)
iBytesRecv += iLenData;
else
iBytesSend += iLenData;
}
/*计算时间间隔*/
QueryPerformanceCounter(&liTimeEnd);
liTimeElapse.QuadPart = liTimeEnd.QuadPart - liTimeStart.QuadPart;
double dTimeElapse = static_cast<double>(liTimeElapse.QuadPart) / liFrequency.QuadPart;
/*统计流量*/
dbpsRecv += static_cast<double>(iBytesRecv) * 8 / dTimeElapse;
dbpsSend += static_cast<double>(iBytesSend) * 8 / dTimeElapse;
/*关闭SIO_RCVALL*/
emRcvallValue = RCVALL_OFF;
if(SOCKET_ERROR == WSAIoctl(s, SIO_RCVALL, &emRcvallValue,
sizeof(emRcvallValue), NULL, 0, &dwBytesReturned, NULL, NULL))
{
printf("WSAIoctl == SOCKET_ERROR, ErrorCode=%d\n", GetLastError());
return false;
}
/*关闭socket*/
closesocket(s);
}
return true;
}
浙公网安备 33010602011771号