windows获取进程流量

来源:互联网 发布:中国家暴数据统计图 编辑:程序博客网 时间:2024/04/28 10:00

铺垫

获取进程使用的端口

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;elsecontinue;/*获取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;elseiPortLocal = 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;elseiBytesSend += 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;}

 

0 0
原创粉丝点击