• 流量监控实战


      以下是我在网上找的一个关于网络流量监控的程序,它类似于360在桌面上的流量悬浮窗口。

      该程序主要实现流量的监控,再加上用按钮控件实现的一个坐标显示的功能,将流量的数据使用图形传达出来,这是一个很好的方式,在很多地方我们都会遇到类似的情况,比如说在做上位机的时候,我们需要将下位机采集到的温湿度等数据实时的显示出来,用该种方式就显得很有水平。

      其实我也是拿到这个工程的代码很看不懂,我们来一段一段的分析,源代码见下文我给出的地址下载。

      首先,建立MFC对话框工程NetTrafficButton。在IDD_NETTRAFFICBUTTON_DIALOG中添加控件,如下图

      在CNetTrafficButtonApp.cpp中添加:

    #include "winnet.h"
    #pragma comment(lib, "winnet.lib")

    注意这里给出的不是wininet.lib,而这个库应该是作者自己写的一个库,从头文件中我找到了两个函数:

    BOOL DLLENTRY NetInit();
    void DLLENTRY NetUnint();

    建立流量处理类MFNetTraffic。其头文件如下:

    /*******************************************
    
        MFTrafficButton
    
        Version:    1.0
        Date:        31.10.2001
        Author:        Michael Fatzi
        Mail:        Michael_Fatzi@hotmail.com
        Copyright 1996-1997, Keith Rule
    
        You may freely use or modify this code provided this
        Copyright is included in all derived versions.
        
        History: 10.2001 Startup
    
        Handy little button control to display current 
        nettraffic as graph in a button.
    
    ********************************************/
    
    // MFNetTraffic.h: interface for the MFNetTraffic class.
    //
    //////////////////////////////////////////////////////////////////////
    
    #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);
        BOOL    GetNetworkInterfaceName(CString *InterfaceName, int index);
        int        GetNetworkInterfacesCount();
        double    GetTraffic(int interfaceNumber);
    
        DWORD    GetInterfaceBandwidth(int 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代码如下:

    /*******************************************
    
        MFTrafficButton
    
        Version:    1.0
        Date:        31.10.2001
        Author:        Michael Fatzi
        Mail:        Michael_Fatzi@hotmail.com
        Copyright 1996-1997, Keith Rule
    
        You may freely use or modify this code provided this
        Copyright is included in all derived versions.
        
        History: 10.2001 Startup
    
        Handy little button control to display current 
        nettraffic as graph in a button.
    
    ********************************************/
    
    // MFNetTraffic.cpp: implementation of the MFNetTraffic class.
    //
    //////////////////////////////////////////////////////////////////////
    
    #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"
    
    //////////////////////////////////////////////////////////////////////
    // Construction/Destruction
    //////////////////////////////////////////////////////////////////////
    
    MFNetTraffic::MFNetTraffic()
    {
        lasttraffic = 0.0;
        CurrentInterface = -1;
        CurrentTrafficType = AllTraffic;
        GetInterfaces();
    }
    
    MFNetTraffic::~MFNetTraffic()
    {
        
    }
    
    // Little helper functions
    // Found them on CodeGuru, but do not know who has written them originally
    
    static PERF_OBJECT_TYPE *FirstObject(PERF_DATA_BLOCK *dataBlock)
    {
      return (PERF_OBJECT_TYPE *) ((BYTE *)dataBlock + dataBlock->HeaderLength);
    }
    
    static PERF_OBJECT_TYPE *NextObject(PERF_OBJECT_TYPE *act)
    {
      return (PERF_OBJECT_TYPE *) ((BYTE *)act + act->TotalByteLength);
    }
    
    static PERF_COUNTER_DEFINITION *FirstCounter(PERF_OBJECT_TYPE *perfObject)
    {
      return (PERF_COUNTER_DEFINITION *) ((BYTE *) perfObject + perfObject->HeaderLength);
    }
    
    static PERF_COUNTER_DEFINITION *NextCounter(PERF_COUNTER_DEFINITION *perfCounter)
    {
      return (PERF_COUNTER_DEFINITION *) ((BYTE *) perfCounter + perfCounter->ByteLength);
    }
    
    static PERF_COUNTER_BLOCK *GetCounterBlock(PERF_INSTANCE_DEFINITION *pInstance)
    {
      return (PERF_COUNTER_BLOCK *) ((BYTE *)pInstance + pInstance->ByteLength);
    }
    
    static PERF_INSTANCE_DEFINITION *FirstInstance (PERF_OBJECT_TYPE *pObject)
    {
      return (PERF_INSTANCE_DEFINITION *)  ((BYTE *) pObject + pObject->DefinitionLength);
    }
    
    static PERF_INSTANCE_DEFINITION *NextInstance (PERF_INSTANCE_DEFINITION *pInstance)
    {
      // next instance is after
      //    this instance + this instances counter data
    
      PERF_COUNTER_BLOCK  *pCtrBlk = GetCounterBlock(pInstance);
    
      return (PERF_INSTANCE_DEFINITION *) ((BYTE *)pInstance + pInstance->ByteLength + pCtrBlk->ByteLength);
    }
    
    static char *WideToMulti(wchar_t *source, char *dest, int size)
    {
      int nLen = WideCharToMultiByte(CP_ACP, 0, source, -1, dest, size, 0, 0);
      dest[nLen] = '\0';
    
      return dest;
    }
    
    /*
        returns the traffic of given interface
    */
    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);
            
            
            // buffer for performance data
            unsigned char *data = new unsigned char [DEFAULT_BUFFER_SIZE];
            // return value from RegQueryValueEx: ignored for this application
            DWORD type;
            // Buffer size
            DWORD size = DEFAULT_BUFFER_SIZE;
            // return value of RegQueryValueEx
            DWORD ret;
            
            // request performance data from network object (index 510) 
            while((ret = RegQueryValueEx(HKEY_PERFORMANCE_DATA, "510", 0, &type, data, &size)) != ERROR_SUCCESS) {
                if(ret == ERROR_MORE_DATA) 
                {
                    // buffer size was too small, increase allocation size
                    size += DEFAULT_BUFFER_SIZE;
                    
                    delete [] data;
                    data = new unsigned char [size];
                } 
                else 
                {
                    // some unspecified error has occured
                    return 1;
                }
            }
            
            PERF_DATA_BLOCK *dataBlockPtr = (PERF_DATA_BLOCK *)data;
            
            // enumerate first object of list
            PERF_OBJECT_TYPE *objectPtr = FirstObject(dataBlockPtr);
            
            // trespassing the list 
            for(int a=0 ; a<(int)dataBlockPtr->NumObjectTypes ; a++) 
            {
                char nameBuffer[255];
                
                // did we receive a network object?
                if(objectPtr->ObjectNameTitleIndex == 510) 
                {
                    // Calculate the offset
                    DWORD processIdOffset = ULONG_MAX;
                    
                    // find first counter 
                    PERF_COUNTER_DEFINITION *counterPtr = FirstCounter(objectPtr);
                    
                    // walking trough the list of objects
                    for(int b=0 ; b<(int)objectPtr->NumCounters ; b++) 
                    {
                        // Check if we received datatype wished
                        if((int)counterPtr->CounterNameTitleIndex == CurrentTrafficType)
                        {
                            processIdOffset = counterPtr->CounterOffset;
                            break;
                        }
                        
                        // watch next counter
                        counterPtr = NextCounter(counterPtr);
                    }
                    
                    if(processIdOffset == ULONG_MAX) {
                        delete [] data;
                        return 1;
                    }
                    
                    
                    // Find first instance
                    PERF_INSTANCE_DEFINITION *instancePtr = FirstInstance(objectPtr);
                    
                    DWORD fullTraffic;
                    DWORD traffic;
                    for(b=0 ; b<objectPtr->NumInstances ; b++) 
                    {
                        // evaluate pointer to name
                        wchar_t *namePtr = (wchar_t *) ((BYTE *)instancePtr + instancePtr->NameOffset);
                        
                        // get PERF_COUNTER_BLOCK of this instance
                        PERF_COUNTER_BLOCK *counterBlockPtr = GetCounterBlock(instancePtr);
                        
                        // now we have the interface name
                        
                        char *pName = WideToMulti(namePtr, nameBuffer, sizeof(nameBuffer));
                        CString iName("");
                        iName.Format("%s",pName);
                        if( iName == "" ) continue;
                    
                        POSITION pos = TotalTraffics.FindIndex(b);
                        if(pos!=NULL)
                        {
                            fullTraffic = *((DWORD *) ((BYTE *)counterBlockPtr + processIdOffset));
                            TotalTraffics.SetAt(pos,fullTraffic);
                        }
    
                        // If the interface the currently selected interface?
                        if(InterfaceName == iName)
                        {
                            traffic = *((DWORD *) ((BYTE *)counterBlockPtr + processIdOffset));
                            double acttraffic = (double)traffic;
                            double trafficdelta;
                            // Do we handle a new interface (e.g. due a change of the interface number
                            if(CurrentInterface != interfaceNumber)
                            {
                                lasttraffic = acttraffic;
                                trafficdelta = 0.0;
                                CurrentInterface = interfaceNumber;
                            }
                            else
                            {
                                trafficdelta = acttraffic - lasttraffic;
                                lasttraffic = acttraffic;
                            }
                            delete [] data;
                            return(trafficdelta);
                        }
                        
                        // next instance
                        instancePtr = NextInstance(instancePtr);
                    }
                }
                
                // next object in list
                objectPtr = NextObject(objectPtr);
            }
            
            delete [] data;
            return 0;
        }
    
        catch(...)
        {
            return 0;
        }
    }
    
    /*
        Enumerate installed interfaces. 
        See comments above
    */
    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 );
            
            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));
                        if( strcmp(pName, "") == 0 ) continue;
                        
                        DWORD bandwith = *((DWORD *) ((BYTE *)counterBlockPtr + processIdOffset));                
                        DWORD tottraff = 0;
    
                        Interfaces.AddTail(CString(pName));
                        Bandwidths.AddTail(bandwith);
                        TotalTraffics.AddTail(tottraff);  // initial 0, just for creating the list
                        
                        instancePtr = NextInstance(instancePtr);
                    }
                }
                objectPtr = NextObject(objectPtr);
            }
            free(data);
            
            return TRUE;
        }
        catch(...)
        {
            return FALSE;
        }
    }
    
    /*
        Returns the count of installed interfaces
    */
    int MFNetTraffic::GetNetworkInterfacesCount()
    {
        return Interfaces.GetCount()-1;
    }
    
    /*
        Returns the name of the given interface (-number)
    */
    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;
    }
    
    /*
        Returns bandwith of interface e.g. 100000 for 100MBit
    */
    DWORD MFNetTraffic::GetInterfaceBandwidth(int index)
    {
        POSITION pos = Bandwidths.FindIndex(index);
        if(pos==NULL)
            return 0;
    
        else 
            return Bandwidths.GetAt(pos) / 8;
    
    }
    
    /*
        Sometime it is nice to know, how much traffic has a specific interface sent and received
    */
    
    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);
    }
    
    /*
        To prevent direct manipulation of member variables....
    */
    void MFNetTraffic::SetTrafficType(int trafficType)
    {
        CurrentTrafficType = trafficType;
    }

    建立处理显示坐标的类MFTrafficButton。

    建立处理画刷的处理类CMemDC。

    #if !defined(AFX_MEMDC_H__CA1D3541_7235_11D1_ABBA_00A0243D1382__INCLUDED_)
    #define AFX_MEMDC_H__CA1D3541_7235_11D1_ABBA_00A0243D1382__INCLUDED_
    
    #if _MSC_VER >= 1000
    #pragma once
    #endif // _MSC_VER >= 1000
    // MemDC.h : header file
    //
    
    //////////////////////////////////////////////////
    // CMemDC - memory DC
    //
    // Author: Keith Rule
    // Email:  keithr@europa.com
    // Copyright 1996-1997, Keith Rule
    //
    // You may freely use or modify this code provided this
    // Copyright is included in all derived versions.
    //
    // History - 10/3/97 Fixed scrolling bug.
    //                   Added print support.
    //           25 feb 98 - fixed minor assertion bug
    //
    // This class implements a memory Device Context
    
    class CMemDC : public CDC
    {
    public:
    
        // constructor sets up the memory DC
        CMemDC(CDC* pDC) : CDC()
        {
            ASSERT(pDC != NULL);
    
            m_pDC = pDC;
            m_pOldBitmap = NULL;
            m_bMemDC = !pDC->IsPrinting();
                  
            if (m_bMemDC)    // Create a Memory DC
            {
                pDC->GetClipBox(&m_rect);
                CreateCompatibleDC(pDC);
                m_bitmap.CreateCompatibleBitmap(pDC, m_rect.Width(), m_rect.Height());
                m_pOldBitmap = SelectObject(&m_bitmap);
                SetWindowOrg(m_rect.left, m_rect.top);
            }
            else        // Make a copy of the relevent parts of the current DC for printing
            {
                m_bPrinting = pDC->m_bPrinting;
                m_hDC       = pDC->m_hDC;
                m_hAttribDC = pDC->m_hAttribDC;
            }
        }
        
        // Destructor copies the contents of the mem DC to the original DC
        ~CMemDC()
        {
            if (m_bMemDC) 
            {    
                // Copy the offscreen bitmap onto the screen.
                m_pDC->BitBlt(m_rect.left, m_rect.top, m_rect.Width(), m_rect.Height(),
                              this, m_rect.left, m_rect.top, SRCCOPY);
    
                //Swap back the original bitmap.
                SelectObject(m_pOldBitmap);
            } else {
                // All we need to do is replace the DC with an illegal value,
                // this keeps us from accidently deleting the handles associated with
                // the CDC that was passed to the constructor.
                m_hDC = m_hAttribDC = NULL;
            }
        }
    
        // Allow usage as a pointer
        CMemDC* operator->() {return this;}
            
        // Allow usage as a pointer
        operator CMemDC*() {return this;}
    
    private:
        CBitmap  m_bitmap;      // Offscreen bitmap
        CBitmap* m_pOldBitmap;  // bitmap originally found in CMemDC
        CDC*     m_pDC;         // Saves CDC passed in constructor
        CRect    m_rect;        // Rectangle of drawing area.
        BOOL     m_bMemDC;      // TRUE if CDC really is a Memory DC.
    };
    
    /////////////////////////////////////////////////////////////////////////////
    
    //{{AFX_INSERT_LOCATION}}
    // Microsoft Developer Studio will insert additional declarations immediately before the previous line.
    
    #endif // !defined(AFX_MEMDC_H__CA1D3541_7235_11D1_ABBA_00A0243D1382__INCLUDED_)
    

      在BOOL CNetTrafficButtonDlg::OnInitDialog()中添加:

        int SelectedInterface    = 0;    // Let us use the first found network connection
        UINT timerresolution    = 1000;    // Well, I think a refresh of the netstatus every second is enough
        UINT gridresolution        = 100;    // To fake the Taskmanager....
    
        m_cTotalTraffic.SetInterfaceNumber(SelectedInterface);                            // Interface to monitor
        m_cTotalTraffic.SelectTrafficType(MFTrafficButton::Traffic_Total);                // In this case the total traffic is monitored
        m_cTotalTraffic.SetInterfaceNumberNotificationFunction(interfaceHasChanged);    // Set the callback handler to get informed...
        m_cTotalTraffic.SetUpdateSpeed(timerresolution, gridresolution);
    
        m_cOutgoing.SetInterfaceNumber(SelectedInterface);
        m_cOutgoing.SelectTrafficType(MFTrafficButton::Traffic_Outgoing);
        m_cOutgoing.SetInterfaceNumberNotificationFunction(interfaceHasChanged);
        m_cOutgoing.SetUpdateSpeed(timerresolution, gridresolution);
    
        m_cIncoming.SetInterfaceNumber(SelectedInterface);
        m_cIncoming.SelectTrafficType(MFTrafficButton::Traffic_Incoming);
        m_cIncoming.SetInterfaceNumberNotificationFunction(interfaceHasChanged);
        m_cIncoming.SetUpdateSpeed(timerresolution, gridresolution);
    View Code

    建立回调函数:static void CALLBACK interfaceHasChanged(int interfacenumber)

    // 'So called' callback function for handling messages from the Buttons
    // Here you can react on interface number changes
    static void CALLBACK interfaceHasChanged(int interfacenumber)
    {
        SelectedInterface = interfacenumber;
        CString text;
        text.Format("NetTrafficButton using Interface: %d",SelectedInterface);
        me->SetWindowText(text);
    }

    运行程序结果如下图:

    源码下载网址:https://code.google.com/p/my-project-galuo/downloads/list

  • 相关阅读:
    【Spring注解驱动开发】二狗子让我给他讲讲@EnableAspectJAutoProxy注解
    【Spring注解驱动开发】你敢信?面试官竟然让我现场搭建一个AOP测试环境!
    【Nginx】如何基于主从模式搭建Nginx+Keepalived双机热备环境?这是最全的一篇了!!
    华为分析+App Linking:一站式解决拉新、留存、促活难
    deeplink跳转快应用返回出现两次系统添加桌面的弹框
    4月26日19:30,#HMS Core Insights#直播系列第二期来了!
    HMS Toolkit自动化环境配置,助您高效集成HMS Core
    全体注意!一大波鸿蒙三方库即将到来
    HMS Toolkit助力开发者高效集成HMS Core
    教你使用一套代码解决出海问题
  • 原文地址:https://www.cnblogs.com/galuo/p/3102205.html
Copyright © 2020-2023  润新知