汕尾海湾 发表于 2024-8-13 07:10:16

基于ICMP(Ping)的多线程网络通道监视程序(QT)开辟

基于ICMP(Ping)的多线程网络通道监视程序(QT)开辟
1、 ICMP原理简介

可参考 ICMP(Ping)功能原理及其C++实现简介 。
2、 网络通道监视程序开辟

设计原理: 通过PING 功能实现服务器、交换机、网闸等设备的网络检测,判定网络的否可达和TTL盘算 。
具备功能:


[*]通过多线程,实现多个网络通道同时检测;
[*]支持动态加包。
[*]支持设置网络延长阈值,超过阈值时提示用户。
①、 界面设计

程序采用QT开辟,UI界面如下图所示:
https://i-blog.csdnimg.cn/direct/bf31d0c468094171b324823d2096d8c3.png#pic_center
中心区域为 QTableWidget 控件。
②、 PING接口封装

IPing.h :
#pragma once


class IPing
{
public:
        IPing();
        ~IPing();

        void SetPackSize(int isize);

        void PingHost(const char* ip, int& timems, int& ttl);

private:
        int sock;
       
        unsigned int m_iTxID;
        unsigned int m_iTxSequeNum;

        unsigned int m_iSendPackageSize;
};


void InitWinSockEnv();

void CleanupWinSockEnv();

IPing.cxx:
#include "IPing.h"

#include <iostream>
#include <string>
#include <chrono>
#include <thread>
#include <iomanip>
#include <winsock2.h>
#pragma comment(lib,"ws2_32.lib")


#define ICMP_PING_DATA_SIZE         40000   //填充数据长度;
#define ICMP_TYPE_PING_REQUEST      8
#define ICMP_TYPE_PING_REPLY          0

#define ICMP_PING_TIMES               1         //Ping次数
#define MAX_BUFFER_SIZE               40100


typedef unsigned char      uint8;
typedef unsigned short               uint16;
typedef unsigned int         uint32;

//ICMP校验和计算
uint16 MakeChecksum(char* icmp_packet, int size)
{
        uint16 * sum = (uint16*)icmp_packet;
        uint32 checksum = 0;
        while (size > 1)
        {
                checksum += ntohs(*sum++);
                size -= sizeof(uint16);
        }

        if (size)
        {
                *sum = *((uint8*)sum);
                checksum += ((*sum << 8) & 0xFF00);
        }

        checksum = (checksum >> 16) + (checksum & 0xffff);
        checksum += checksum >> 16;

        return (uint16)(~checksum);
}

IPing::IPing()
{
        sock = 0;
        m_iTxID = 0;
        m_iTxSequeNum = 0;

        m_iSendPackageSize = 32;

        SOCKET s = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP);
        sock = s;
}

IPing::~IPing()
{
        if (sock > 0)
        {
                closesocket(sock);
        }
}

void IPing::SetPackSize(int isize)
{
        m_iSendPackageSize = isize;
}

void IPing::PingHost(const char* ip, int& timems, int& ttl)
{
        std::string strHost = std::string(ip);
    if (strHost.length()< 5)
    {
                timems = -1;
                ttl = -1;
                return;
    }

        struct sockaddr_in pingaddr;
        memset((char *)&pingaddr, 0, sizeof(pingaddr));
        pingaddr.sin_family = AF_INET;
        pingaddr.sin_port = 0;
        pingaddr.sin_addr.s_addr = inet_addr(strHost.c_str());

        for (int ii = 0; ii < ICMP_PING_TIMES; ++ii)
        {
                //组帧
                uint8 ucCmdBuf = { 0 };
                uint8* pCurr = ucCmdBuf;

                *pCurr++ = ICMP_TYPE_PING_REQUEST;               //Type
                *pCurr++ = 0x00;                                               //Code
                *pCurr++ = 0x00;                                               //Checksum
                *pCurr++ = 0x00;                                               //Checksum
                *pCurr++ = HIBYTE(m_iTxID);                               //Identifier
                *pCurr++ = LOBYTE(m_iTxID);                               //Identifier
                *pCurr++ = HIBYTE(m_iTxSequeNum);      //Sequence Number
                *pCurr++ = LOBYTE(m_iTxSequeNum);             //Sequence Number

                auto send_clock = std::chrono::system_clock::now();
                DWORD dwSendTime = std::chrono::duration_cast<std::chrono::milliseconds>(send_clock.time_since_epoch()).count();;
                *pCurr++ = HIBYTE(HIWORD(dwSendTime));   //Current TickCount
                *pCurr++ = LOBYTE(HIWORD(dwSendTime));   //Current TickCount
                *pCurr++ = HIBYTE(LOWORD(dwSendTime));   //Current TickCount
                *pCurr++ = LOBYTE(LOWORD(dwSendTime));   //Current TickCount

                //Data
                for (int k = 0; k < m_iSendPackageSize - 4; ++k)
                {
                        *pCurr++ = 0x61 + (k % 20);
                }

                uint16 usCheckSum = MakeChecksum((char*)ucCmdBuf, pCurr - ucCmdBuf);
                ucCmdBuf = HIBYTE(usCheckSum);
                ucCmdBuf = LOBYTE(usCheckSum);


                int txlen = sendto(sock, (char *)&ucCmdBuf, pCurr - ucCmdBuf, 0, (struct sockaddr *) &pingaddr, sizeof(struct sockaddr_in));

                uint8 ucRxBuf = { 0 };

                struct sockaddr_in rxaddr;
                memset((char *)&rxaddr, 0, sizeof(rxaddr));
                rxaddr.sin_family = AF_INET;
                rxaddr.sin_port = 0;
                rxaddr.sin_addr.s_addr = inet_addr(strHost.c_str());
                int iSize = sizeof(struct sockaddr_in);


                do
                {
                        int rxlen = recvfrom(sock, (char *)&ucRxBuf, sizeof(ucRxBuf), 0, (struct sockaddr *)&rxaddr, &iSize);   
                        if (rxaddr.sin_addr.S_un.S_addr == pingaddr.sin_addr.S_un.S_addr)
                        {       
                                if (rxlen >= 0)
                                {
                                        //IP帧获取TTL
                                        ttl = ucRxBuf;

                                        //跳过IP Header 20个字节
                                        uint8* pIcmpFrame = ucRxBuf + 20;

                                        //Type和Code
                                        uint8 ucType = pIcmpFrame;
                                        uint8 ucCode = pIcmpFrame;
                                        if (ucCode != 0x00 || ucType != 0x00)
                                                goto GO_ON;

                                        //比对ID和序号
                                        uint16 iRxID = pIcmpFrame * 256 + pIcmpFrame;
                                        uint16 iRxSequeNum = pIcmpFrame * 256 + pIcmpFrame;
                                        if (iRxID == m_iTxID && iRxSequeNum == m_iTxSequeNum)
                                        {
                                                DWORD dwTimeTransmit = pIcmpFrame * 256 * 256 * 256 + pIcmpFrame * 256 * 256 + pIcmpFrame * 256 + pIcmpFrame;

                                                auto now = std::chrono::system_clock::now();
                                                DWORD dwNowTime = std::chrono::duration_cast<std::chrono::milliseconds>(now.time_since_epoch()).count();

                                                timems = dwNowTime - dwTimeTransmit;
                                        }
                                        else
                                                goto GO_ON;

                                }
                                else
                                {
                                        timems = -1;//异常
                                }

                                m_iTxID++;
                                m_iTxSequeNum++;

                                break;
                        }

        GO_ON:
                        auto current_clock = std::chrono::system_clock::now();
                        DWORD dwCurrentTime = std::chrono::duration_cast<std::chrono::milliseconds>(current_clock.time_since_epoch()).count();;
                        if (dwCurrentTime - dwSendTime > 2000)
                        {
                                timems = -2;//超时
                                return;
                        }
                }
                while (true);
        }

}


void InitWinSockEnv()
{
        WSADATA wsaData;
        WSAStartup(MAKEWORD(2, 2), &wsaData);
}


void CleanupWinSockEnv()
{
        WSACleanup();
}
③、 PING多线程接口封装

多线程采用 std::thread 实现,线程函数封装如下:
/************************************************************************/
/*                                                                      */
/*@WrapExecPing函数功能:线程函数,调用PING接口                     */
/*                                                                      */
/*@aipaddr, bipaddr参数: 监视的节点IPA和IPB地址                        */
/*@atimems, btimems参数: IPA地址和IPB地址PING响应时间                  */
/*@attl, bttl参数:       IPA地址和IPB地址PING响应TTL值               */
/*@stopf 参数:         停止线程任务标志位                            */
/*@package_size 参数:    PING包大小                                 */
/*@asnd, bsnd参数:       IPA地址和IPB地址PING次数                      */
/*@f 参数:               线程结束标志位                              */
/*                                                                      */
/************************************************************************/
void WrapExecPing(std::string aipaddr, std::string bipaddr, int& atimems, int& attl, int& btimems, int& bttl, bool& stopf,int package_size,int& asnd,int&bsnd, bool& f)
{
        IPing aping;
        IPing bping;

    //设置PING包大小
        aping.SetPackSize(package_size);
        bping.SetPackSize(package_size);

        f = true;

        while (!stopf)
        {
                auto start = std::chrono::system_clock::now();
                DWORD dwStartTime = std::chrono::duration_cast<std::chrono::milliseconds>(start.time_since_epoch()).count();

                if (aipaddr.length() > 5)
                {
            //执行IP地址A的PING
                        aping.PingHost(aipaddr.c_str(), atimems, attl);
                        asnd++;
                }
                else
                        std::this_thread::sleep_for(std::chrono::milliseconds(500));
                       
                if (bipaddr.length() > 5)
                {
            //执行IP地址B的PING
                        bping.PingHost(bipaddr.c_str(), btimems, bttl);
                        bsnd++;
                }
                else
                        std::this_thread::sleep_for(std::chrono::milliseconds(500));

                auto now = std::chrono::system_clock::now();
                DWORD dwNowTime = std::chrono::duration_cast<std::chrono::milliseconds>(now.time_since_epoch()).count();
                if (dwNowTime - dwStartTime < 500)
                {
                        std::this_thread::sleep_for(std::chrono::milliseconds(800));
                }
        }

        f = false;
}
④、 QT主程序开辟

【1】、 界面初始化

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);

        //初始化Windows套接字环境
        InitWinSock();

        glb_bStopF = false;
       
        //初始化表格控件;
        initTableWidget();

        //初始化PING包大小复选框;
        initComboBox();

        //初始化延迟超限报警阈值;
        initLineEdit();
       
        ui->pushButtonStop->setEnabled(false);

        //设置控件样式表QSS
        setStyleSheet("QMainWindow{ background-color: #365a7a; } QLabel{ color:#E0E0E0; font-weight:bold; }");
       
        ui->pushButtonStart->setStyleSheet("QPushButton{ background-color: transparent;color: #f0f0f0; font-weight:bold;} QPushButton:hover{ background-color:white; color:gray; font-weight:thin; border-radius:4px;} QPushButton:disabled{ color:gray;}");
        ui->pushButtonStop->setStyleSheet("QPushButton{ background-color: transparent;color: #f0f0f0; font-weight:bold;} QPushButton:hover{ background-color:white; color:gray; font-weight:thin; border-radius:4px;} QPushButton:disabled{ color:gray;}");
        ui->lineEdit->setStyleSheet("QLineEdit{background-color:#D9D9D9; color:gray;}");
        ui->comboBox->setStyleSheet("QComboBox{color:gray;}");

        //信号槽定义;
        connect(ui->pushButtonStart, SIGNAL(clicked()), this, SLOT(onButtonStart()));
        connect(ui->pushButtonStop, SIGNAL(clicked()), this, SLOT(onButtonStop()));
}
表格控件初始化
void MainWindow::initTableWidget()
{
        //加载nodecfg.ini文件

        extern bool LoadNodeConfig(CHostInfoArray& arry);
        if (false == LoadNodeConfig(arry) || arry.size() <= 0)
        {
                QMessageBox::warning(this, QString::fromLocal8Bit("提示"), QString::fromLocal8Bit("《nodecfg.ini》打开失败!"));
                return;
        }

        //初始化表格列
        ui->tableWidget->setEditTriggers(QAbstractItemView::NoEditTriggers);
        ui->tableWidget->setColumnCount(MAX_COLUMN_NUM);

        QStringList headerList;
        headerList << QString::fromLocal8Bit("网络节点名称");
        headerList << QString::fromLocal8Bit("A网IP地址");
        headerList << QString::fromLocal8Bit("B网IP地址");
        headerList << QString::fromLocal8Bit("A网延时");
        headerList << QString::fromLocal8Bit("A网TTL");
        headerList << QString::fromLocal8Bit("B网延时");
        headerList << QString::fromLocal8Bit("B网TTL");
        headerList << QString::fromLocal8Bit("PING次数");
        ui->tableWidget->setHorizontalHeaderLabels(headerList);
        ui->tableWidget->horizontalHeader()->setStyleSheet("QHeaderView::section {background-color: #365a7a; color: rgb(220,220,220); font-weight:bold;}");
        ui->tableWidget->verticalHeader()->setStyleSheet("QHeaderView::section {background-color: #365a7a; color: rgb(220,220,220); font-weight:bold;}");
        ui->tableWidget->setColumnWidth(0, 120);
        ui->tableWidget->setColumnWidth(1, 140);
        ui->tableWidget->setColumnWidth(2, 140);
        ui->tableWidget->setColumnWidth(7, 160);


        //行
        int iSize = arry.size();
        if (iSize > 0)
        {
                ui->tableWidget->setRowCount(iSize);

                for (int ii = 0; ii < iSize;++ii)
                {
                        ui->tableWidget->setItem(ii, 0, new QTableWidgetItem());    ui->tableWidget->item(ii, 0)->setText(QString::fromStdString(arry.strHostName)); ui->tableWidget->item(ii, 0)->setData(Qt::DisplayRole, QString::fromStdString(arry.strHostName));
                        ui->tableWidget->setItem(ii, 1, new QTableWidgetItem());    ui->tableWidget->item(ii, 1)->setText(QString::fromStdString(arry.strIPA));
                        ui->tableWidget->setItem(ii, 2, new QTableWidgetItem());    ui->tableWidget->item(ii, 2)->setText(QString::fromStdString(arry.strIPB));
                        ui->tableWidget->setItem(ii, 3, new QTableWidgetItem());
                        ui->tableWidget->setItem(ii, 4, new QTableWidgetItem());
                        ui->tableWidget->setItem(ii, 5, new QTableWidgetItem());
                        ui->tableWidget->setItem(ii, 6, new QTableWidgetItem());
                        ui->tableWidget->setItem(ii, 7, new QTableWidgetItem());
                }
        }
}
复选框控件初始化
void MainWindow::initComboBox()
{
        ui->comboBox->addItem("32", 32);
        ui->comboBox->addItem("128", 128);
        ui->comboBox->addItem("256", 256);
        ui->comboBox->addItem("512",512);
        ui->comboBox->addItem("1024", 1024);
        ui->comboBox->addItem("2048", 2048);
        ui->comboBox->addItem("2500", 2500);
        ui->comboBox->addItem("3000", 3000);
        ui->comboBox->addItem("4096", 4096);
        ui->comboBox->addItem("5000", 5000);
        ui->comboBox->addItem("8000", 8000);
        ui->comboBox->addItem("10000", 10000);
        ui->comboBox->addItem("13000", 13000);
        ui->comboBox->addItem("15000", 15000);
        ui->comboBox->addItem("18000", 18000);
        ui->comboBox->addItem("24000", 24000);
        ui->comboBox->addItem("28000", 28000);
        ui->comboBox->addItem("32000", 32000);
        ui->comboBox->addItem("36000", 36000);

        ui->comboBox->setCurrentIndex(0);
}
编辑框控件初始化
void MainWindow::initLineEdit()
{
        ui->lineEdit->setText("200");
}
【2】、 启动多线程

使用 std::thread线程,
void MainWindow::StartPingTask()
{
        int iSize = arry.size();
        if (iSize <= 0)
        {
                onButtonStop();
                return;
        }

        //报警阈值
        int alarmval = ui->lineEdit->text().toInt();

        //Ping包大小;
        int index = ui->comboBox->currentIndex();
        int package_size = ui->comboBox->itemData(index).toInt();

        SPINGINFO* pPingInfo = new SPINGINFO;

        for (int i = 0; i < iSize; i++)
        {
                pPingInfo.host = arry;
                pPingInfo.attl = -1;
                pPingInfo.bttl = -1;
                pPingInfo.atimems = -1;
                pPingInfo.btimems = -1;
                pPingInfo.asnd = 0;
                pPingInfo.bsnd = 0;

                std::thread T1(WrapExecPing, pPingInfo.host.strIPA, pPingInfo.host.strIPB, std::ref(pPingInfo.atimems), std::ref(pPingInfo.attl), std::ref(pPingInfo.btimems), std::ref(pPingInfo.bttl), std::ref(glb_bStopF), package_size, std::ref(pPingInfo.asnd), std::ref(pPingInfo.bsnd), std::ref(pPingInfo.runf));


                pPingInfo.t = std::move(T1);

                std::this_thread::sleep_for(std::chrono::milliseconds(10));
        }
}
【3】、 完整代码

#include "mainwindow.h"#include "ui_mainwindow.h"#include "QMessageBox"#include "public.h"#include "IPing.h"#include <thread>#include <chrono>#defineMAX_COLUMN_NUM   8CHostInfoArray arry;bool glb_bStopF = false;MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);

        //初始化Windows套接字环境
        InitWinSock();

        glb_bStopF = false;
       
        //初始化表格控件;
        initTableWidget();

        //初始化PING包大小复选框;
        initComboBox();

        //初始化延迟超限报警阈值;
        initLineEdit();
       
        ui->pushButtonStop->setEnabled(false);

        //设置控件样式表QSS
        setStyleSheet("QMainWindow{ background-color: #365a7a; } QLabel{ color:#E0E0E0; font-weight:bold; }");
       
        ui->pushButtonStart->setStyleSheet("QPushButton{ background-color: transparent;color: #f0f0f0; font-weight:bold;} QPushButton:hover{ background-color:white; color:gray; font-weight:thin; border-radius:4px;} QPushButton:disabled{ color:gray;}");
        ui->pushButtonStop->setStyleSheet("QPushButton{ background-color: transparent;color: #f0f0f0; font-weight:bold;} QPushButton:hover{ background-color:white; color:gray; font-weight:thin; border-radius:4px;} QPushButton:disabled{ color:gray;}");
        ui->lineEdit->setStyleSheet("QLineEdit{background-color:#D9D9D9; color:gray;}");
        ui->comboBox->setStyleSheet("QComboBox{color:gray;}");

        //信号槽定义;
        connect(ui->pushButtonStart, SIGNAL(clicked()), this, SLOT(onButtonStart()));
        connect(ui->pushButtonStop, SIGNAL(clicked()), this, SLOT(onButtonStop()));
}
MainWindow::~MainWindow(){        CleanWinSock();    delete ui;}void MainWindow::InitWinSock(){    //初始化Windows套接字环境        InitWinSockEnv();}void MainWindow::CleanWinSock(){        CleanupWinSockEnv();}void MainWindow::initTableWidget(){        //加载网络节点设置文件nodecfg.ini        extern bool LoadNodeConfig(CHostInfoArray& arry);        if (false == LoadNodeConfig(arry) || arry.size() <= 0)        {                QMessageBox::warning(this, QString::fromLocal8Bit("提示"), QString::fromLocal8Bit("《nodecfg.ini》打开失败!"));                return;        }        //初始化表格列        ui->tableWidget->setEditTriggers(QAbstractItemView::NoEditTriggers);        ui->tableWidget->setColumnCount(MAX_COLUMN_NUM);        QStringList headerList;        headerList << QString::fromLocal8Bit("网络节点名称");        headerList << QString::fromLocal8Bit("A网IP地址");        headerList << QString::fromLocal8Bit("B网IP地址");        headerList << QString::fromLocal8Bit("A网延时");        headerList << QString::fromLocal8Bit("A网TTL");        headerList << QString::fromLocal8Bit("B网延时");        headerList << QString::fromLocal8Bit("B网TTL");        headerList << QString::fromLocal8Bit("PING次数");        ui->tableWidget->setHorizontalHeaderLabels(headerList);        ui->tableWidget->horizontalHeader()->setStyleSheet("QHeaderView::section {background-color: #365a7a; color: rgb(220,220,220); font-weight:bold;}");        ui->tableWidget->verticalHeader()->setStyleSheet("QHeaderView::section {background-color: #365a7a; color: rgb(220,220,220); font-weight:bold;}");        ui->tableWidget->setColumnWidth(0, 120);        ui->tableWidget->setColumnWidth(1, 140);        ui->tableWidget->setColumnWidth(2, 140);        ui->tableWidget->setColumnWidth(7, 160);        //行,插入记录        int iSize = arry.size();        if (iSize > 0)        {                ui->tableWidget->setRowCount(iSize);                for (int ii = 0; ii < iSize;++ii)                {                        ui->tableWidget->setItem(ii, 0, new QTableWidgetItem());    ui->tableWidget->item(ii, 0)->setText(QString::fromStdString(arry.strHostName)); ui->tableWidget->item(ii, 0)->setData(Qt::DisplayRole, QString::fromStdString(arry.strHostName));                        ui->tableWidget->setItem(ii, 1, new QTableWidgetItem());    ui->tableWidget->item(ii, 1)->setText(QString::fromStdString(arry.strIPA));                        ui->tableWidget->setItem(ii, 2, new QTableWidgetItem());    ui->tableWidget->item(ii, 2)->setText(QString::fromStdString(arry.strIPB));                        ui->tableWidget->setItem(ii, 3, new QTableWidgetItem());                        ui->tableWidget->setItem(ii, 4, new QTableWidgetItem());                        ui->tableWidget->setItem(ii, 5, new QTableWidgetItem());                        ui->tableWidget->setItem(ii, 6, new QTableWidgetItem());                        ui->tableWidget->setItem(ii, 7, new QTableWidgetItem());                }        }        }void MainWindow::initComboBox(){    //PING包大小选项        ui->comboBox->addItem("32", 32);        ui->comboBox->addItem("128", 128);        ui->comboBox->addItem("256", 256);        ui->comboBox->addItem("512",512);        ui->comboBox->addItem("1024", 1024);        ui->comboBox->addItem("2048", 2048);        ui->comboBox->addItem("2500", 2500);        ui->comboBox->addItem("3000", 3000);        ui->comboBox->addItem("4096", 4096);        ui->comboBox->addItem("5000", 5000);        ui->comboBox->addItem("8000", 8000);        ui->comboBox->addItem("10000", 10000);        ui->comboBox->addItem("13000", 13000);        ui->comboBox->addItem("15000", 15000);        ui->comboBox->addItem("18000", 18000);        ui->comboBox->addItem("24000", 24000);        ui->comboBox->addItem("28000", 28000);        ui->comboBox->addItem("32000", 32000);        ui->comboBox->addItem("36000", 36000);        ui->comboBox->setCurrentIndex(0);}void MainWindow::initLineEdit(){    //报警阈值,单元毫秒        ui->lineEdit->setText("200");}//开始检测void MainWindow::onButtonStart(){        ui->comboBox->setEnabled(false);        ui->lineEdit->setEnabled(false);        ui->pushButtonStart->setEnabled(false);        ui->pushButtonStop->setEnabled(true);        glb_bStopF = false;        ClearTableWidget();        StartPingTask();}void MainWindow::onButtonStop(){        glb_bStopF = true;}/************************************************************************//*                                                                      *//*@WrapExecPing函数功能: 线程函数,调用PING接口                        *//*                                                                      *//*@aipaddr, bipaddr参数: 监视的节点IPA和IPB地址                        *//*@atimems, btimems参数: IPA地址和IPB地址PING响应时间                  *//*@attl, bttl参数:       IPA地址和IPB地址PING响应TTL值               *//*@stopf 参数:         停止线程任务标志位                            *//*@package_size 参数:    PING包大小                                 *//*@asnd, bsnd参数:       IPA地址和IPB地址PING次数                      *//*@f 参数:               线程结束标志位                              *//*                                                                      *//************************************************************************/void WrapExecPing(std::string aipaddr, std::string bipaddr, int& atimems, int& attl, int& btimems, int& bttl, bool& stopf,int package_size,int& asnd,int&bsnd, bool& f){        IPing aping;        IPing bping;        aping.SetPackSize(package_size);        bping.SetPackSize(package_size);        f = true;        while (!stopf)        {                auto start = std::chrono::system_clock::now();                DWORD dwStartTime = std::chrono::duration_cast<std::chrono::milliseconds>(start.time_since_epoch()).count();                if (aipaddr.length() > 5)                {                        aping.PingHost(aipaddr.c_str(), atimems, attl);                        asnd++;                }                else                         std::this_thread::sleep_for(std::chrono::milliseconds(500));                                        if (bipaddr.length() > 5)                {                        bping.PingHost(bipaddr.c_str(), btimems, bttl);                        bsnd++;                }                else                        std::this_thread::sleep_for(std::chrono::milliseconds(500));                auto now = std::chrono::system_clock::now();                DWORD dwNowTime = std::chrono::duration_cast<std::chrono::milliseconds>(now.time_since_epoch()).count();                if (dwNowTime - dwStartTime < 500)                {                        std::this_thread::sleep_for(std::chrono::milliseconds(800));                }        }        f = false;}void MainWindow::ClearTableWidget(){        int iRowCount = ui->tableWidget->rowCount();        for (int k = 0; k < iRowCount; ++k)        {                for (int i = 3; i < MAX_COLUMN_NUM;++i)                {                        ui->tableWidget->item(k, i)->setText(QString(""));                }        }}void MainWindow::StartPingTask(){        int iSize = arry.size();        if (iSize <= 0)        {                onButtonStop();                return;        }        //报警阈值        int alarmval = ui->lineEdit->text().toInt();        //Ping包大小;        int index = ui->comboBox->currentIndex();        int package_size = ui->comboBox->itemData(index).toInt();        SPINGINFO* pPingInfo = new SPINGINFO;        for (int i = 0; i < iSize; i++)        {                pPingInfo.host = arry;                pPingInfo.attl = -1;                pPingInfo.bttl = -1;                pPingInfo.atimems = -1;                pPingInfo.btimems = -1;                pPingInfo.asnd = 0;                pPingInfo.bsnd = 0;      //启动线程                std::thread T1(WrapExecPing, pPingInfo.host.strIPA, pPingInfo.host.strIPB, std::ref(pPingInfo.atimems), std::ref(pPingInfo.attl), std::ref(pPingInfo.btimems), std::ref(pPingInfo.bttl), std::ref(glb_bStopF), package_size, std::ref(pPingInfo.asnd), std::ref(pPingInfo.bsnd), std::ref(pPingInfo.runf));                pPingInfo.t = std::move(T1);                std::this_thread::sleep_for(std::chrono::milliseconds(10));        }    //界面更新        do         {                if (glb_bStopF) break;                int iRowCount = ui->tableWidget->rowCount();                for (int k = 0; k < iRowCount;++k)                {                        QString strHostName = ui->tableWidget->item(k, 0)->data(Qt::DisplayRole).toString();                        for (int n = 0; n < iSize;++n)                        {                                if (strHostName.toStdString() == pPingInfo.host.strHostName)                                {                                        if (pPingInfo.atimems == -1)                                                ui->tableWidget->item(k, 3)->setText(QString("---"));                                        else if (pPingInfo.atimems == -2)                                                ui->tableWidget->item(k, 3)->setText(QString::fromLocal8Bit("超时"));                                        else                                        {                                                ui->tableWidget->item(k, 3)->setText(QString("%1ms").arg(pPingInfo.atimems));                                                if (pPingInfo.atimems > alarmval)                                                        ui->tableWidget->item(k, 3)->setBackgroundColor(QColor(255, 0, 0));    //超限,红色提示                                                else                                                        ui->tableWidget->item(k, 3)->setBackgroundColor(QColor(255, 255, 255));                                        }                                                                                        if (pPingInfo.attl < 0)                                                ui->tableWidget->item(k, 4)->setText(QString("---"));                                        else                                                ui->tableWidget->item(k, 4)->setText(QString("%1").arg(pPingInfo.attl));                                        if (pPingInfo.btimems == -1)                                                ui->tableWidget->item(k, 5)->setText(QString("---"));                                        else if (pPingInfo.btimems == -2)                                                ui->tableWidget->item(k, 5)->setText(QString::fromLocal8Bit("超时"));                                        else                                        {                                                ui->tableWidget->item(k, 5)->setText(QString("%1ms").arg(pPingInfo.btimems));                                                if (pPingInfo.btimems > alarmval)                                                        ui->tableWidget->item(k, 5)->setBackgroundColor(QColor(255, 0, 0));   //超限,红色提示                                                else                                                        ui->tableWidget->item(k, 5)->setBackgroundColor(QColor(255, 255, 255));                                        }                                                                                        if (pPingInfo.bttl < 0)                                                ui->tableWidget->item(k, 6)->setText(QString("---"));                                        else                                                ui->tableWidget->item(k, 6)->setText(QString("%1").arg(pPingInfo.bttl));                                        QString strSndFrame = QString::fromLocal8Bit("A网:%1 | B网:%2").arg(pPingInfo.asnd, 3, 10, QLatin1Char('0')).arg(pPingInfo.bsnd, 3, 10, QLatin1Char('0'));                                        ui->tableWidget->item(k, 7)->setText(strSndFrame);                                        break;                                }                        }                }        }         while (true);        ui->pushButtonStop->setEnabled(false);        bool bRunningF = false;        do         {                bRunningF = false;                for (int ii = 0; ii < iSize; ++ii)                {                        if (pPingInfo.runf == true)                        {                                ui->pushButtonStop->setText(QString::fromLocal8Bit("停止中..."));                                bRunningF = true;                                break;                        }                }        }         while (bRunningF);                for (int ii = 0; ii < iSize;++ii)        {                pPingInfo.t.detach();        }        delete []pPingInfo;        ui->pushButtonStop->setText(QString::fromLocal8Bit("停止检测"));        ui->pushButtonStart->setEnabled(true);        ui->pushButtonStop->setEnabled(false);        ui->comboBox->setEnabled(true);        ui->lineEdit->setEnabled(true);} 3、 运行结果

https://i-blog.csdnimg.cn/direct/bbc0ac66cb644101a6659151ae8eceb6.png#pic_center

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
页: [1]
查看完整版本: 基于ICMP(Ping)的多线程网络通道监视程序(QT)开辟