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
", sNameProc.c_str());
		return false;
	}

	/*获取所有网卡IP*/
	std::vector<std::string> vecHostIp;
	if(!GetLocalHostIp(vecHostIp))
	{
		printf("GetLocalHostIp == false
");
		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
", GetLastError());
			return false;
		}

		/*设置非阻塞*/
		DWORD dwCmdParam = 1;
		if(SOCKET_ERROR == ioctlsocket(s, FIONBIO, &dwCmdParam))
		{
			printf("ioctlsocket(s, FIONBIO, &dwCmdParam) == SOCKET_ERROR, ErrorCode=%d
", 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
", 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
", 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
", GetLastError());
				break;
			}
			if(0 == iLenRecv)
			{
				printf("recv == SOCKET_ERROR, Connection Closed
");
				break;
			}

			cBuffer[iLenRecv] = '';

			/*验证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
", GetLastError());
			return false;
		}

		/*关闭socket*/
		closesocket(s);
	}

	return true;
}
原文地址:https://www.cnblogs.com/chaikefusibushiji/p/7475608.html