Visual C++ 2017网络编程实战
上QQ阅读APP看书,第一时间看更新

2.5 获取本地计算机的IP协议统计数据

通过函数GetIpStatistics可以获取当前主机的IP协议的统计数据,比如已经收到了多少个数据包。该函数声明如下:

    ULONG GetIpStatistics(PMIB_IPSTATS pStats);

其中,参数pStats指向MIB_IPSTATS结构的指针,该结构接收本地计算机的IP统计信息。如果函数成功,返回值为NO_ERROR。如果函数失败,返回值是以下错误代码:

·ERROR_INVALID_PARAMETER:pStats参数为空,或者GetIpStatistics无法写入pStats参数指向的内存。

结构体MIB_IPSTATS的定义如下:

    typedef struct _MIB_IPSTATS
    {
    // dwForwarding指定IPv4或IPv6的每个协议转发状态,而不是接口的转发状态
        DWORD        dwForwarding;
        DWORD  dwDefaultTTL;                   //起始于特定计算机上的数据包的默认初始生存时间
        DWORD        dwInReceives;             //接收到的数据包数
        DWORD        dwInHdrErrors;            //接收到的有头部错误的数据包数
        DWORD        dwInAddrErrors;           //收到的具有地址错误的数据包数
        DWORD        dwForwDatagrams;          //转发的数据包数
        DWORD        dwInUnknownProtos;        //接收到的具有未知协议的数据包数
        DWORD        dwInDiscards;             //丢弃的接收数据包的数目
        DWORD        dwInDelivers;             //已传递的接收数据包的数目
    // IP请求传输的传出数据包数。此数目不包括转发的数据包
        DWORD        dwOutRequests;
        DWORD        dwRoutingDiscards;        //丢弃的传出数据包的数目
        DWORD        dwOutDiscards;            //丢弃的传输数据包数
    //此计算机没有到目标IP地址的路由的数据包数,这些数据包被丢弃
        DWORD        dwOutNoRoutes;
    //允许碎片数据包的所有部分到达的时间量。如果在这段时间内所有数据块都没有到达,数据包将被丢弃
        DWORD        dwReasmTimeout;
        DWORD        dwReasmReqds;             //需要重新组装的数据包数
        DWORD        dwReasmOks;               //成功重新组合的数据包数
        DWORD        dwReasmFails;             //无法重新组合的数据包数
        DWORD        dwFragOks;                //成功分段的数据包数
    //由于IP头未指定分段而未分段的数据包数,这些数据包被丢弃
        DWORD        dwFragFails;
        DWORD        dwFragCreates;            //创建的片段数
        DWORD        dwNumIf;                  //接口的数目
        DWORD        dwNumAddr;                //与此计算机关联的IP地址数
        DWORD        dwNumRoutes;              //IP路由选项卡中的路由数
    } MIB_IPSTATS, *PMIB_IPSTATS;

GetIpStatistics函数返回当前计算机上IPv4的统计信息。如果还需要获得IPv6的IP统计信息,可以用其扩展函数GetIpStatisticsEx。

【例2.5】获取本机的IP统计数据

(1)新建一个对话框工程,工程名是Demo。

(2)切换到资源视图,在对话框上放一个列表框和一个按钮。其中,列表框的ID是IDC_LIST。双击按钮,为其添加事件响应代码:

    void CDemoDlg::OnTest()
    {
    CListBox* pListBox = (CListBox*)GetDlgItem(IDC_LIST);
    pListBox->ResetContent();

    MIB_IPSTATS IPStats;

    //获得IP协议统计信息
    if (GetIpStatistics(&IPStats) != NO_ERROR)
    {
         return;
    }

    CString strText = _T("");
    strText.Format(_T("IP forwarding enabled or disabled:%d"),
         IPStats.dwForwarding);
    pListBox->AddString(strText);
    strText.Format(_T("default time-to-live:%d"),
         IPStats.dwDefaultTTL);
    pListBox->AddString(strText);
    strText.Format(_T("datagrams received:%d"),
         IPStats.dwInReceives);
    pListBox->AddString(strText);
    strText.Format(_T("received header errors:%d"),
         IPStats.dwInHdrErrors);
    pListBox->AddString(strText);
    strText.Format(_T("received address errors:%d"),
         IPStats.dwInAddrErrors);
    pListBox->AddString(strText);
    strText.Format(_T("datagrams forwarded:%d"),
         IPStats.dwForwDatagrams);
    pListBox->AddString(strText);
    strText.Format(_T("datagrams with unknown protocol:%d"),
         IPStats.dwInUnknownProtos);
    pListBox->AddString(strText);
    strText.Format(_T("received datagrams discarded:%d"),
         IPStats.dwInDiscards);
    pListBox->AddString(strText);
    strText.Format(_T("received datagrams delivered:%d"),
         IPStats.dwInDelivers);
    pListBox->AddString(strText);
    strText.Format(_T("outgoing datagrams requested to send:%d"),
         IPStats.dwOutRequests);
    pListBox->AddString(strText);
    strText.Format(_T("outgoing datagrams discarded:%d"),
         IPStats.dwOutDiscards);
    pListBox->AddString(strText);
    strText.Format(_T("sent datagrams discarded:%d"),
         IPStats.dwOutDiscards);
    pListBox->AddString(strText);
    strText.Format(_T("datagrams for which no route exists:%d"),
         IPStats.dwOutNoRoutes);
    pListBox->AddString(strText);
    strText.Format(_T("datagrams for which all frags did not arrive:%d"),
         IPStats.dwReasmTimeout);
    pListBox->AddString(strText);
    strText.Format(_T("datagrams requiring reassembly:%d"),
         IPStats.dwReasmReqds);
    pListBox->AddString(strText);
    strText.Format(_T("successful reassemblies:%d"),
         IPStats.dwReasmOks);
    pListBox->AddString(strText);
    strText.Format(_T("failed reassemblies:%d"),
         IPStats.dwReasmFails);
    pListBox->AddString(strText);
    strText.Format(_T("successful fragmentations:%d"),
         IPStats.dwFragOks);
    pListBox->AddString(strText);
    strText.Format(_T("failed fragmentations:%d"),
         IPStats.dwFragFails);
    pListBox->AddString(strText);
    strText.Format(_T("datagrams fragmented:%d"),
         IPStats.dwFragCreates);
    pListBox->AddString(strText);
    strText.Format(_T("number of interfaces on computer:%d"),
         IPStats.dwNumIf);
    pListBox->AddString(strText);
    strText.Format(_T("number of IP address on computer:%d"),
         IPStats.dwNumAddr);
    pListBox->AddString(strText);
    strText.Format(_T("number of routes in routing table:%d"),
         IPStats.dwNumRoutes);
    pListBox->AddString(strText);
    }

在DemoDlg.cpp开头包括文件和引用库文件:

    #include <Iphlpapi.h>
    #pragma comment(lib,"IPHlpApi.lib")

(3)保存工程并运行,结果如图2-8所示。

图2-8