MFC网速及流量监控程序的实现(一)

    网上看到了一个实例,到处在转载,原作者是谁不详,这里用到它里面的一个类。主要功能是获取网卡的流量信息:下面贴出这个类的源代码,以作备份:

MFNetTraffic.h

#if !defined(AFX_MFNETTRAFFIC_H__9CA9C41F_F929_4F26_BD1F_2B5827090494__INCLUDED_)
#define AFX_MFNETTRAFFIC_H__9CA9C41F_F929_4F26_BD1F_2B5827090494__INCLUDED_
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
#include <afxtempl.h>
class MFNetTraffic  
{
public:
	enum TrafficType //流量类型
	{
		AllTraffic		= 388,//总的流量
		IncomingTraffic	= 264,//输入流量
		OutGoingTraffic	= 506 //输出流量
	};
	void	SetTrafficType(int trafficType);		//设置流量类型
	DWORD	GetInterfaceTotalTraffic(int index);	//得到index索引接口的总流量
	BOOL	GetNetworkInterfaceName(CString *InterfaceName, int index);//得到网络接口名字
	int		GetNetworkInterfacesCount();			//得到接口的数目
	double	GetTraffic(int interfaceNumber);		//得到流量
	DWORD	GetInterfaceBandwidth(int index);		//得到index索引接口的带宽
	MFNetTraffic();
	virtual ~MFNetTraffic();

private:
	BOOL		GetInterfaces();
	double		lasttraffic;
	CStringList Interfaces;		
	CList < DWORD, DWORD &>		Bandwidths;	//带宽
	CList < DWORD, DWORD &>		TotalTraffics;//总的流量
	int CurrentInterface;
	int CurrentTrafficType;
};
#endif // !defined(AFX_MFNETTRAFFIC_H__9CA9C41F_F929_4F26_BD1F_2B5827090494__INCLUDED_)


MFNetTraffic.cpp

#include "stdafx.h"
#include "MFNetTraffic.h"
#include "float.h"
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
#include "winperf.h"
MFNetTraffic::MFNetTraffic()
{
	lasttraffic = 0.0;
	CurrentInterface = -1;
	CurrentTrafficType = AllTraffic;
	GetInterfaces();
}
MFNetTraffic::~MFNetTraffic()
{
	
}
PERF_OBJECT_TYPE *FirstObject(PERF_DATA_BLOCK *dataBlock)
{
  return (PERF_OBJECT_TYPE *) ((BYTE *)dataBlock + dataBlock->HeaderLength);
}
PERF_OBJECT_TYPE *NextObject(PERF_OBJECT_TYPE *act)
{
  return (PERF_OBJECT_TYPE *) ((BYTE *)act + act->TotalByteLength);
}
PERF_COUNTER_DEFINITION *FirstCounter(PERF_OBJECT_TYPE *perfObject)
{
  return (PERF_COUNTER_DEFINITION *) ((BYTE *) perfObject + perfObject->HeaderLength);
}
PERF_COUNTER_DEFINITION *NextCounter(PERF_COUNTER_DEFINITION *perfCounter)
{
  return (PERF_COUNTER_DEFINITION *) ((BYTE *) perfCounter + perfCounter->ByteLength);
}
PERF_COUNTER_BLOCK *GetCounterBlock(PERF_INSTANCE_DEFINITION *pInstance)
{
  return (PERF_COUNTER_BLOCK *) ((BYTE *)pInstance + pInstance->ByteLength);
}
PERF_INSTANCE_DEFINITION *FirstInstance (PERF_OBJECT_TYPE *pObject)
{
  return (PERF_INSTANCE_DEFINITION *)  ((BYTE *) pObject + pObject->DefinitionLength);
}
PERF_INSTANCE_DEFINITION *NextInstance (PERF_INSTANCE_DEFINITION *pInstance)
{
  PERF_COUNTER_BLOCK  *pCtrBlk = GetCounterBlock(pInstance);
  return (PERF_INSTANCE_DEFINITION *) ((BYTE *)pInstance + pInstance->ByteLength + pCtrBlk->ByteLength);
}
char *WideToMulti(wchar_t *source, char *dest, int size)
{
  WideCharToMultiByte(CP_ACP, 0, source, -1, dest, size, 0, 0);
  return dest;
}



//得到接口号为interfaceNumber的接口流量
double MFNetTraffic::GetTraffic(int interfaceNumber)
{
	try
	{
#define DEFAULT_BUFFER_SIZE 40960L
		POSITION pos;
		CString InterfaceName;
		pos = Interfaces.FindIndex(interfaceNumber);
		if(pos==NULL)
			return 0.0;
		//得到当前的接口名字
		InterfaceName = Interfaces.GetAt(pos);
		//为性能数据缓冲
		unsigned char *data = new unsigned char [DEFAULT_BUFFER_SIZE];
		// 从RegQueryValueEx返回的值:本例中忽略改变量
		DWORD type;
		// 缓冲的尺寸
		DWORD size = DEFAULT_BUFFER_SIZE;
		// RegQueryValueEx返回的值
		DWORD ret;
		// 从网络对象(索引是510)查询性能数据
		while((ret = RegQueryValueEx(
			HKEY_PERFORMANCE_DATA, "510", NULL, &type, data, &size)) != ERROR_SUCCESS) 
		{
			if(ret == ERROR_MORE_DATA) 
			{
				// 缓冲尺寸太小,增加内存分配
				size += DEFAULT_BUFFER_SIZE;		
				delete [] data;
				data = new unsigned char [size];
			} 
			else 
			{
				// 未定义的错误
				return 1;
			}
		}
		//性能数据块
		PERF_DATA_BLOCK *dataBlockPtr = (PERF_DATA_BLOCK *)data;
		//枚举链表中第一个对象
		PERF_OBJECT_TYPE *objectPtr = FirstObject(dataBlockPtr);
		//遍历链表 
		for(int a=0 ; a<(int)dataBlockPtr->NumObjectTypes ; a++) 
		{
			char nameBuffer[255];
			// 判断是否是网络对象索引号是510
			if(objectPtr->ObjectNameTitleIndex == 510) 
			{
				// 偏移变量
				DWORD processIdOffset = ULONG_MAX;
				// 找到第一个计数器
				PERF_COUNTER_DEFINITION *counterPtr = FirstCounter(objectPtr);
				// 遍历链表
				for(int b=0 ; b<(int)objectPtr->NumCounters ; b++) 
				{
					// 判断接收的数据类型是否是我们需要的
					if((int)counterPtr->CounterNameTitleIndex == CurrentTrafficType)
						processIdOffset = counterPtr->CounterOffset;
					// 下一个计数器
					counterPtr = NextCounter(counterPtr);
				}
				//数据类型不是我们需要的
				if(processIdOffset == ULONG_MAX) {
					delete [] data;
					return 1;
				}
				// 找到第一个实列(instance)
				PERF_INSTANCE_DEFINITION *instancePtr = FirstInstance(objectPtr);
				DWORD fullTraffic;
				DWORD traffic;
				//遍历整个实列
				for(b=0 ; b<objectPtr->NumInstances ; b++) 
				{
					wchar_t *namePtr = (wchar_t *) ((BYTE *)instancePtr + instancePtr->NameOffset);		
					// 得到这个实列的PERF_COUNTER_BLOCK
					PERF_COUNTER_BLOCK *counterBlockPtr = GetCounterBlock(instancePtr);
					// 现在我们得到了接口的名字
					char *pName = WideToMulti(namePtr, nameBuffer, sizeof(nameBuffer));
					CString iName;
					iName.Format("%s",pName);
					POSITION pos = TotalTraffics.FindIndex(b);
					if(pos!=NULL)
					{
						fullTraffic = *((DWORD *) ((BYTE *)counterBlockPtr + processIdOffset));
						TotalTraffics.SetAt(pos,fullTraffic);
					}
					// 如果当前的接口就是我们选择的接口
					if(InterfaceName == iName)
					{
						traffic = *((DWORD *) ((BYTE *)counterBlockPtr + processIdOffset));
						double acttraffic = (double)traffic;
						double trafficdelta;
						// 判断处理的接口是否是新的
						if(CurrentInterface != interfaceNumber)
						{
							lasttraffic = acttraffic;
							trafficdelta = 0.0;
							CurrentInterface = interfaceNumber;
						}
						else
						{
							trafficdelta = acttraffic - lasttraffic;
							lasttraffic = acttraffic;
						}
						delete [] data;
						return(trafficdelta);
					}
					//下一个实列
					instancePtr = NextInstance(instancePtr);
				}
			}
			// 下一个对象
			objectPtr = NextObject(objectPtr);
		}
		delete [] data;
		return 0;
	}
	catch(...)
	{
		return 0;
	}
}


//枚举安装的接口
BOOL MFNetTraffic::GetInterfaces()
{
	try
	{
#define DEFAULT_BUFFER_SIZE 40960L
		
		Interfaces.RemoveAll();
		unsigned char *data = (unsigned char*)malloc(DEFAULT_BUFFER_SIZE);
		DWORD type;
		DWORD size = DEFAULT_BUFFER_SIZE;
		DWORD ret;
		char s_key[4096];
		sprintf( s_key , "%d" , 510 );
		//RegQueryValueEx的固定调用格式		
		while((ret = RegQueryValueEx(HKEY_PERFORMANCE_DATA, s_key, 0, &type, data, &size)) != ERROR_SUCCESS) {
			while(ret == ERROR_MORE_DATA) 
			{
				size += DEFAULT_BUFFER_SIZE;
				data = (unsigned char*) realloc(data, size);
			} 
			if(ret != ERROR_SUCCESS)
			{
				return FALSE;
			}
		}
		//得到数据块		
		PERF_DATA_BLOCK	 *dataBlockPtr = (PERF_DATA_BLOCK *)data;
		//得到第一个对象
		PERF_OBJECT_TYPE *objectPtr = FirstObject(dataBlockPtr);
		for(int a=0 ; a<(int)dataBlockPtr->NumObjectTypes ; a++) 
		{
			char nameBuffer[255];
			if(objectPtr->ObjectNameTitleIndex == 510) 
			{
				DWORD processIdOffset = ULONG_MAX;
				PERF_COUNTER_DEFINITION *counterPtr = FirstCounter(objectPtr);
				for(int b=0 ; b<(int)objectPtr->NumCounters ; b++) 
				{
					if(counterPtr->CounterNameTitleIndex == 520)
						processIdOffset = counterPtr->CounterOffset;
					counterPtr = NextCounter(counterPtr);
				}
				if(processIdOffset == ULONG_MAX) {
					free(data);
					return 1;
				}
				PERF_INSTANCE_DEFINITION *instancePtr = FirstInstance(objectPtr);
				for(b=0 ; b<objectPtr->NumInstances ; b++) 
				{
					wchar_t *namePtr = (wchar_t *) ((BYTE *)instancePtr + instancePtr->NameOffset);
					PERF_COUNTER_BLOCK *counterBlockPtr = GetCounterBlock(instancePtr);
					char *pName = WideToMulti(namePtr, nameBuffer, sizeof(nameBuffer));
					DWORD bandwith = *((DWORD *) ((BYTE *)counterBlockPtr + processIdOffset));				
					DWORD tottraff = 0;
					Interfaces.AddTail(CString(pName));
					Bandwidths.AddTail(bandwith);
					TotalTraffics.AddTail(tottraff); 
					instancePtr = NextInstance(instancePtr);
				}
			}
			objectPtr = NextObject(objectPtr);
		}
		free(data);
		return TRUE;
	}
	catch(...)
	{
		return FALSE;
	}
}


//返回安装的接口数
int MFNetTraffic::GetNetworkInterfacesCount()
{
	return Interfaces.GetCount()-1;
}


//返回接口名称
BOOL MFNetTraffic::GetNetworkInterfaceName(CString *InterfaceName, int index)
{
	POSITION pos = Interfaces.FindIndex(index);
	if(pos==NULL)
		return FALSE;
	InterfaceName->Format("%s",Interfaces.GetAt(pos));
	return TRUE;
}


//返回接口带宽
DWORD MFNetTraffic::GetInterfaceBandwidth(int index)
{
	POSITION pos = Bandwidths.FindIndex(index);
	if(pos==NULL)
		return 0;
	else 
		return Bandwidths.GetAt(pos) / 8;
}


//具体接口接收和发送的数据量
DWORD MFNetTraffic::GetInterfaceTotalTraffic(int index)
{
	DWORD	totaltraffic = 0;
	POSITION	pos;
	pos= TotalTraffics.FindIndex(index);
	if(pos!=NULL)
	{
		totaltraffic = TotalTraffics.GetAt(pos); 
		if(totaltraffic == 0.0)
		{
			GetTraffic(index);
			pos= TotalTraffics.FindIndex(index);
			if(pos!=NULL)
			{
				totaltraffic = TotalTraffics.GetAt(pos); 
			}
		}
	}
	return(totaltraffic);
}


void MFNetTraffic::SetTrafficType(int trafficType)
{
	CurrentTrafficType = trafficType;
}


下篇文章介绍如何实现网速和流量的监测,主要就是利用上述类中的函数,下面放上几张程序的截图:


网速悬浮小窗口


双击展开详情










  • 6
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值