如何查询网络状态,比如网络流量等。在网络断开的时候是否有消息捕获?
谢谢!

解决方案 »

  1.   

    获取本地网络负荷可以通过截获局域网内的数据包实现流量监控,然后除以时间可以大致获得负荷情况,代码如下(只实现截包,分析自己按要求补充)
    int main(int argc, char ** argv)
    {
        SOCKET s;
        struct sockaddr_in addr;
        char msg[MAX_MSG_LENGTH];
        UINT bRcvAll;
        UINT length;
        WSADATA wsd;
        WSABUF wsbuf;
        DWORD    dwNumSend,
                dwFlags;
        long srcipaddr = 0;
        long destipaddr = 0;
        int nRecvlen;
        int timestamp;    if (argc < 5)
        {
            printf("Please input the arguments !\n");
            printf("example : powerspy 20.20.20.233 20.20.20.233 20.20.20.233 10\n");
            return -1;
        }    if (WSAStartup(MAKEWORD(2, 2), &wsd) != 0)
        {
            printf("WSAStartup() failed!\n");
            return -1;
        }
        
        bRcvAll = TRUE;
        addr.sin_addr.S_un.S_addr = inet_addr(argv[1]);
        addr.sin_port = htons(7705);
        addr.sin_family = AF_INET;
        s = socket(AF_INET, SOCK_RAW, IPPROTO_IP);
        if (s == INVALID_SOCKET)
        {
            printf("socket() failed; %d\n", WSAGetLastError());
            return -1;
        }
        if (bind(s, (struct sockaddr *)(&addr), sizeof(addr)) == SOCKET_ERROR)
        {
            printf("bind() failed; %d\n", WSAGetLastError());
            return -1;
        }
        if (WSAIoctl(s, SIO_RCVALL, &bRcvAll, sizeof(bRcvAll), NULL, 0,
            &length, NULL, NULL) == SOCKET_ERROR)
        {
            printf("WSAIoctl() failed; %d\n", WSAGetLastError());
            return -1;
        }
        dwFlags = 0;
        wsbuf.buf = msg;
        wsbuf.len = MAX_MSG_LENGTH;
    //    printf("%s\n", argv[0]);
    //    printf("%s\n", argv[1]);
    //    printf("%s\n", argv[2]);
    //    printf("%s\n", argv[3]);
        
    //    if (strcmp(argv[1], "0") == 0)
    //    {
    //        srcipaddr = 0;
    //    }
    //    else
    //    {
        srcipaddr = inet_addr(argv[2]);
    //    }
    //    if (strcmp(argv[2], "0") == 0)
    //    {
    //        destipaddr = 0;
    //    }
    //    else
    //    {
        destipaddr = inet_addr(argv[3]);
    //    }
        timestamp = atoi(argv[4]) * 1000;
        srcipaddr = htonl(srcipaddr);
        destipaddr = htonl(destipaddr);    while (1)
        {
            if (timestamp != 0)
                Sleep(timestamp);
            nRecvlen = WSARecv(s, &wsbuf, 1, &dwNumSend, &dwFlags, NULL, NULL);
        
            
            if (nRecvlen != SOCKET_ERROR)
            {
                DecodeIPHeader(&wsbuf, srcipaddr, 0, destipaddr, 0);
    //            recvproc(msg, nRecvlen);
            }
    //        else
    //        {
    //            printf("Recv failed!\n");
    //        }
        }
        if (closesocket(s) == SOCKET_ERROR)
        {
            printf("closesocket() failed; %d\n", WSAGetLastError());
        }
        
        if (WSACleanup() == SOCKET_ERROR)
        {
            printf("WSACleanup() failed; %d\n", WSAGetLastError());
            return -1;
        }
    }void recvproc(char * msg, int len)
    {
        printf("Recv ok!\n");
    }
    其实也可以通过snmp获得网络负荷情况,而且可以取得异地网络的负荷情况,但是需要异地网络中必须有一些关键服务器运行snmp代理(windows下也有该代理,可以通过添加/删除组件进行安装,缺省不安装)并且你必须知道代理的共同体密码(很多商业的网络管理软件都是这么做的,感兴趣可以去查查)
    至于cpu情况,代码如下:
    // cpusagent.cpp (Windows NT/2000)
    //
    // Getting the CPU usage in percent on Windows NT/2000
    //
    // (c)2000 Ashot Oganesyan K, SmartLine, Inc
    // mailto:[email protected], http://www.protect-me.com, http://www.codepile.com#include <windows.h>
    #include <conio.h>
    #include <stdio.h>#define SystemBasicInformation       0
    #define SystemPerformanceInformation 2
    #define SystemTimeInformation        3#define Li2Double(x) ((double)((x).HighPart) * 4.294967296E9 + (double)((x).LowPart))typedef struct
    {
        DWORD   dwUnknown1;
        ULONG   uKeMaximumIncrement;
        ULONG   uPageSize;
        ULONG   uMmNumberOfPhysicalPages;
        ULONG   uMmLowestPhysicalPage;
        ULONG   uMmHighestPhysicalPage;
        ULONG   uAllocationGranularity;
        PVOID   pLowestUserAddress;
        PVOID   pMmHighestUserAddress;
        ULONG   uKeActiveProcessors;
        BYTE    bKeNumberProcessors;
        BYTE    bUnknown2;
        WORD    wUnknown3;
    } SYSTEM_BASIC_INFORMATION;typedef struct
    {
        LARGE_INTEGER   liIdleTime;
        DWORD           dwSpare[76];
    } SYSTEM_PERFORMANCE_INFORMATION;typedef struct
    {
        LARGE_INTEGER liKeBootTime;
        LARGE_INTEGER liKeSystemTime;
        LARGE_INTEGER liExpTimeZoneBias;
        ULONG         uCurrentTimeZoneId;
        DWORD         dwReserved;
    } SYSTEM_TIME_INFORMATION;
    // ntdll!NtQuerySystemInformation (NT specific!)
    //
    // The function copies the system information of the
    // specified type into a buffer
    //
    // NTSYSAPI
    // NTSTATUS
    // NTAPI
    // NtQuerySystemInformation(
    //    IN UINT SystemInformationClass,    // information type
    //    OUT PVOID SystemInformation,       // pointer to buffer
    //    IN ULONG SystemInformationLength,  // buffer size in bytes
    //    OUT PULONG ReturnLength OPTIONAL   // pointer to a 32-bit
    //                                       // variable that receives
    //                                       // the number of bytes
    //                                       // written to the buffer 
    // );
    typedef LONG (WINAPI *PROCNTQSI)(UINT,PVOID,ULONG,PULONG);PROCNTQSI NtQuerySystemInformation;
    void main(void)
    {
        SYSTEM_PERFORMANCE_INFORMATION SysPerfInfo;
        SYSTEM_TIME_INFORMATION        SysTimeInfo;
        SYSTEM_BASIC_INFORMATION       SysBaseInfo;
        double                         dbIdleTime;
        double                         dbSystemTime;
        LONG                           status;
        LARGE_INTEGER                  liOldIdleTime = {0,0};
        LARGE_INTEGER                  liOldSystemTime = {0,0};    NtQuerySystemInformation = (PROCNTQSI)GetProcAddress(
                                              GetModuleHandle("ntdll"),
                                             "NtQuerySystemInformation"
                                             );    if (!NtQuerySystemInformation)
            return;    // get number of processors in the system
        status = NtQuerySystemInformation(SystemBasicInformation,&SysBaseInfo,sizeof(SysBaseInfo),NULL);
        if (status != NO_ERROR)
            return;
        
        printf("\nCPU Usage (press any key to exit):    ");
        while(!_kbhit())
        {
            // get new system time
            status = NtQuerySystemInformation(SystemTimeInformation,&SysTimeInfo,sizeof(SysTimeInfo),0);
            if (status!=NO_ERROR)
                return;        // get new CPU's idle time
            status = NtQuerySystemInformation(SystemPerformanceInformation,&SysPerfInfo,sizeof(SysPerfInfo),NULL);
            if (status != NO_ERROR)
                return;        // if it's a first call - skip it
           if (liOldIdleTime.QuadPart != 0)
           {
                // CurrentValue = NewValue - OldValue
                dbIdleTime = Li2Double(SysPerfInfo.liIdleTime) - Li2Double(liOldIdleTime);
                dbSystemTime = Li2Double(SysTimeInfo.liKeSystemTime) - Li2Double(liOldSystemTime);            // CurrentCpuIdle = IdleTime / SystemTime
                dbIdleTime = dbIdleTime / dbSystemTime;            // CurrentCpuUsage% = 100 - (CurrentCpuIdle * 100) / NumberOfProcessors
                dbIdleTime = 100.0 - dbIdleTime * 100.0 / (double)SysBaseInfo.bKeNumberProcessors + 0.5;            printf("\b\b\b\b%3d%%",(UINT)dbIdleTime);
           }        // store new CPU's idle and system time
            liOldIdleTime = SysPerfInfo.liIdleTime;
            liOldSystemTime = SysTimeInfo.liKeSystemTime;
            
            // wait one second
            Sleep(1000);
        }
        printf("\n");
    }
      

  2.   

    我测试了一下Win2k以上版本使用的NotifyAddrChange可以完成上面的功能,但是那是要等到地址分配好了才发送这样的请求。因此显示好像没有taskbar的图标速度快。因此觉得taskbar应该不是调用这个接口函数的。
      

  3.   

    WinpCap 的示例中有一个取网络流量的例子
    判断网络断开?用线程查询可以吗