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

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

1、 ICMP原理简介

可参考 ICMP(Ping)功能原理及其C++实现简介 。

2、 网络通道监视程序开发

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

具备功能:

  • 通过多线程,实现多个网络通道同时检测;
  • 支持动态加包。
  • 支持设置网络延迟阈值,超过阈值时提示用户。

①、 界面设计

程序采用QT开发,UI界面如下图所示:

在这里插入图片描述

中心区域为 QTableWidget 控件。

②、 PING接口封装

IPing.h :

#pragma onceclass 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               40100typedef 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[MAX_BUFFER_SIZE] = { 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 Numberauto 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//Datafor (int k = 0; k < m_iSendPackageSize - 4; ++k){*pCurr++ = 0x61 + (k % 20);}uint16 usCheckSum = MakeChecksum((char*)ucCmdBuf, pCurr - ucCmdBuf);ucCmdBuf[2] = HIBYTE(usCheckSum);ucCmdBuf[3] = LOBYTE(usCheckSum);int txlen = sendto(sock, (char *)&ucCmdBuf, pCurr - ucCmdBuf, 0, (struct sockaddr *) &pingaddr, sizeof(struct sockaddr_in));uint8 ucRxBuf[MAX_BUFFER_SIZE] = { 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帧获取TTLttl = ucRxBuf[8];//跳过IP Header 20个字节uint8* pIcmpFrame = ucRxBuf + 20;//Type和Codeuint8 ucType = pIcmpFrame[0];uint8 ucCode = pIcmpFrame[1];if (ucCode != 0x00 || ucType != 0x00)goto GO_ON;//比对ID和序号uint16 iRxID = pIcmpFrame[4] * 256 + pIcmpFrame[5];uint16 iRxSequeNum = pIcmpFrame[6] * 256 + pIcmpFrame[7];if (iRxID == m_iTxID && iRxSequeNum == m_iTxSequeNum){DWORD dwTimeTransmit = pIcmpFrame[8] * 256 * 256 * 256 + pIcmpFrame[9] * 256 * 256 + pIcmpFrame[10] * 256 + pIcmpFrame[11];auto now = std::chrono::system_clock::now();DWORD dwNowTime = std::chrono::duration_cast<std::chrono::milliseconds>(now.time_since_epoch()).count();timems = dwNowTime - dwTimeTransmit;}elsegoto 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的PINGaping.PingHost(aipaddr.c_str(), atimems, attl);asnd++;}else std::this_thread::sleep_for(std::chrono::milliseconds(500));if (bipaddr.length() > 5){//执行IP地址B的PINGbping.PingHost(bipaddr.c_str(), btimems, bttl);bsnd++;}elsestd::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);//设置控件样式表QSSsetStyleSheet("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[ii].strHostName)); ui->tableWidget->item(ii, 0)->setData(Qt::DisplayRole, QString::fromStdString(arry[ii].strHostName));ui->tableWidget->setItem(ii, 1, new QTableWidgetItem());    ui->tableWidget->item(ii, 1)->setText(QString::fromStdString(arry[ii].strIPA));ui->tableWidget->setItem(ii, 2, new QTableWidgetItem());    ui->tableWidget->item(ii, 2)->setText(QString::fromStdString(arry[ii].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[iSize];for (int i = 0; i < iSize; i++){pPingInfo[i].host = arry[i];pPingInfo[i].attl = -1;pPingInfo[i].bttl = -1;pPingInfo[i].atimems = -1;pPingInfo[i].btimems = -1;pPingInfo[i].asnd = 0;pPingInfo[i].bsnd = 0;std::thread T1(WrapExecPing, pPingInfo[i].host.strIPA, pPingInfo[i].host.strIPB, std::ref(pPingInfo[i].atimems), std::ref(pPingInfo[i].attl), std::ref(pPingInfo[i].btimems), std::ref(pPingInfo[i].bttl), std::ref(glb_bStopF), package_size, std::ref(pPingInfo[i].asnd), std::ref(pPingInfo[i].bsnd), std::ref(pPingInfo[i].runf));pPingInfo[i].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>#define  MAX_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);//设置控件样式表QSSsetStyleSheet("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.iniextern 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[ii].strHostName)); ui->tableWidget->item(ii, 0)->setData(Qt::DisplayRole, QString::fromStdString(arry[ii].strHostName));ui->tableWidget->setItem(ii, 1, new QTableWidgetItem());    ui->tableWidget->item(ii, 1)->setText(QString::fromStdString(arry[ii].strIPA));ui->tableWidget->setItem(ii, 2, new QTableWidgetItem());    ui->tableWidget->item(ii, 2)->setText(QString::fromStdString(arry[ii].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++;}elsestd::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[iSize];for (int i = 0; i < iSize; i++){pPingInfo[i].host = arry[i];pPingInfo[i].attl = -1;pPingInfo[i].bttl = -1;pPingInfo[i].atimems = -1;pPingInfo[i].btimems = -1;pPingInfo[i].asnd = 0;pPingInfo[i].bsnd = 0;//启动线程std::thread T1(WrapExecPing, pPingInfo[i].host.strIPA, pPingInfo[i].host.strIPB, std::ref(pPingInfo[i].atimems), std::ref(pPingInfo[i].attl), std::ref(pPingInfo[i].btimems), std::ref(pPingInfo[i].bttl), std::ref(glb_bStopF), package_size, std::ref(pPingInfo[i].asnd), std::ref(pPingInfo[i].bsnd), std::ref(pPingInfo[i].runf));pPingInfo[i].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[n].host.strHostName){if (pPingInfo[n].atimems == -1)ui->tableWidget->item(k, 3)->setText(QString("---"));else if (pPingInfo[n].atimems == -2)ui->tableWidget->item(k, 3)->setText(QString::fromLocal8Bit("超时"));else{ui->tableWidget->item(k, 3)->setText(QString("%1ms").arg(pPingInfo[n].atimems));if (pPingInfo[n].atimems > alarmval)ui->tableWidget->item(k, 3)->setBackgroundColor(QColor(255, 0, 0));    //超限,红色提示elseui->tableWidget->item(k, 3)->setBackgroundColor(QColor(255, 255, 255));}if (pPingInfo[n].attl < 0)ui->tableWidget->item(k, 4)->setText(QString("---"));elseui->tableWidget->item(k, 4)->setText(QString("%1").arg(pPingInfo[n].attl));if (pPingInfo[n].btimems == -1)ui->tableWidget->item(k, 5)->setText(QString("---"));else if (pPingInfo[n].btimems == -2)ui->tableWidget->item(k, 5)->setText(QString::fromLocal8Bit("超时"));else{ui->tableWidget->item(k, 5)->setText(QString("%1ms").arg(pPingInfo[n].btimems));if (pPingInfo[n].btimems > alarmval)ui->tableWidget->item(k, 5)->setBackgroundColor(QColor(255, 0, 0));     //超限,红色提示elseui->tableWidget->item(k, 5)->setBackgroundColor(QColor(255, 255, 255));}if (pPingInfo[n].bttl < 0)ui->tableWidget->item(k, 6)->setText(QString("---"));elseui->tableWidget->item(k, 6)->setText(QString("%1").arg(pPingInfo[n].bttl));QString strSndFrame = QString::fromLocal8Bit("A网:%1 | B网:%2").arg(pPingInfo[n].asnd, 3, 10, QLatin1Char('0')).arg(pPingInfo[n].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[ii].runf == true){ui->pushButtonStop->setText(QString::fromLocal8Bit("停止中..."));bRunningF = true;break;}}} while (bRunningF);for (int ii = 0; ii < iSize;++ii){pPingInfo[ii].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、 运行效果

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/400263.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【应用层协议】自定义协议 {定义结构化数据;数据格式转换:序列化和反序列化,使用json库进行数据格式交换;分包和解包:为报文内容添加报头}

一、简单了解TCP协议&#xff08;引子&#xff09; 1.1 三次握手 三次握手就是客户端向服务端发起连接的过程 服务器初始化 调用socket&#xff0c;创建套接字文件 调用bind&#xff0c;将当前的文件描述符和ip/port绑定在一起&#xff1b;如果这个端口已经被其他进程占用了&…

外贸12年,通过6个方法,成交几千万订单

做外贸有12个年头了&#xff0c;各种各样的方法都有试过&#xff0c;我成交的这几千万订单&#xff0c;大部分都是通过这6个方法来的&#xff0c;下面我来给大家整理分享一下。 1.谷歌搜索 谷歌搜索算是做外贸入门级的基础技能了&#xff0c;要做好外贸&#xff0c;这个技能一…

86.小米相机修改拍照(尺寸,画幅,比例)的方法

目录 1.打开相机&#xff0c;拍照模式&#xff0c;上面有个箭头或三个点&#xff0c;点击 2.点击画幅 3.点击你想要的画幅即可。 想要修改手机照片的&#xff08;尺寸&#xff0c;画幅&#xff0c;比例&#xff09;时&#xff0c;总会去找分辨率&#xff0c;其实并不是&…

Leetcode - 周赛410

目录 一&#xff0c;3248. 矩阵中的蛇 二&#xff0c;3249. 统计好节点的数目 三&#xff0c;3250. 单调数组对的数目 I dfs记忆化 dfs记忆化1&#xff1a;1改递推 四&#xff0c;3251. 单调数组对的数目 II 一&#xff0c;3248. 矩阵中的蛇 本题就是一道纯模拟题&#x…

django高校毕业生就业推荐系统-计算机毕业设计源码26096

摘 要 当前就业市场竞争激烈&#xff0c;高校毕业生面临着就业难的问题&#xff0c;同时企业也面临招聘难、选人难的挑战。为了更好地对接高校毕业生和企业之间的需求&#xff0c;为毕业生提供个性化的就业求着信息&#xff0c;开发一套充分利用Django和Python技术实现的毕业生…

中科院TOP“灌水神刊”合集!年发文量动辄数千篇,TOP的地位,4区的录用率!

【SciencePub学术】本期&#xff0c;给大家推荐几本环境领域的“灌水神刊”&#xff01;均隶属于中科院TOP刊之列&#xff0c;但是每年庞大的发文量致使投稿接收率极高&#xff01;话不多说&#xff0c;想“灌水”的建议收藏&#xff01; 01 年刊文量4000 Journal of Cleaner …

【sgCreateAPIFunction】自定义小工具:敏捷开发→自动化生成API接口方法代码片段脚本(接口方法代码生成工具)

sgCreateAPIFunction源码 <template><!-- 前往https://blog.csdn.net/qq_37860634/article/details/141159084 查看使用说明 --><div :class"$options.name"><div class"sg-head">接口方法生成工具<el-dropdown:show-timeou…

Redis操作--RedisTemplate(一)介绍

一、介绍 1、简介 RedisTemplate 是 Spring Data Redis 提供的一个高级抽象&#xff0c;由 Spring 官方提供的方便操作 Redis 数据库的一个工具类&#xff0c;支持模板设计模式&#xff0c;使得操作 Redis 更加符合 Spring 的编程模型。还支持序列化机制&#xff0c;可以处理…

第二证券:虚拟现实概念强势,博士眼镜三连板,星星科技涨停

虚拟现实概念14日盘中再度走强&#xff0c;到发稿&#xff0c;硕贝德、博士眼镜、星星科技“20cm”涨停&#xff0c;亚世光电、亿道信息、卓翼科技亦涨停&#xff0c;佳禾智能涨超9%。 值得注意的是&#xff0c;博士眼镜已连续3个交易日涨停。公司昨日在出资者互动途径表示&am…

电脑开机后出现bootmgr is missing原因及解决方法

最近有网友问我为什么我电脑开机后出现bootmgr is missing&#xff0c;这个提示意思是:意思是启动管理器丢失&#xff0c;说明bootmgr损坏或者丢失&#xff0c;系统无法读取到这个必要的启动信息导致无法启动。原因有很多&#xff0c;比如我们采用的是uefi引导&#xff0c;而第…

离职保密协议是什么?怎么样才是合法的?如何维护公司权益?

“商贾之道&#xff0c;在于诚信&#xff1b;机密之重&#xff0c;犹胜千金。” 在历史的长河中&#xff0c;商业机密一直是商家兴衰成败的关键。 时至今日&#xff0c;随着科技的飞速发展&#xff0c;信息时代的浪潮更是将商业秘密的保护推向了新的高度。 离职保密协议&…

思科CCIE最新考证流程

CCIE CCIE&#xff0c;全称Cisco Certified Internetwork Expert,是美国Cisco公司于1993年开始推出的专家级认证考试。被全球公认为IT业最权威的认证&#xff0c;是全球Internetworking领域中最顶级的认证证书。 CCIE方向 CCIE主要有六大方向&#xff1a;企业基础架构Enterp…

重修设计模式-行为型-状态模式

重修设计模式-行为型-状态模式 先了解一下状态机的概念&#xff0c;状态机是软件编程中对一种状态场景的抽象表达&#xff0c;构成状态机三要素是&#xff1a;状态&#xff08;State&#xff09;、事件&#xff08;Event&#xff09;、动作&#xff08;Action&#xff09;&…

【测试】趣味五子棋项目测试报告

一、项目概述以及本次测试的目标 本项目是基于Web的五子棋实时对战应用&#xff0c;为用户提供多人实时游戏体验&#xff1b;项目采用了前后端分离的方法来实现&#xff0c;使用了数据库来存储相关的数据&#xff1b;前端主要有四个页面构成&#xff1a;登录页面&#xff0c;注…

多重背包问题

文章目录 朴素算法基本思想代码 二进制优化算法基本思想代码 单调队列优化多重背包基本思想代码 多重背包我们其实可以看成为01背包和完全背包的组合。也可以把多重背包问题只转换成01背包问题&#xff0c;我们一起来看看解题思路。 朴素算法 基本思想 比如第i件物品有s个,我…

作业08.13

一、TCP机械臂测试 通过w(红色臂角度增大)s&#xff08;红色臂角度减小&#xff09;d&#xff08;蓝色臂角度增大&#xff09;a&#xff08;蓝色臂角度减小&#xff09;按键控制机械臂 注意&#xff1a;关闭计算机的杀毒软件&#xff0c;电脑管家&#xff0c;防火墙 1&#x…

CRC校验算法详解、C语言实现

一、前言 1.1 CRC算法介绍 CRC&#xff08;Cyclic Redundancy Check&#xff09;校验算法是一种广泛应用于数据通信和存储系统中的错误检测方法&#xff0c;主要用于检测数据在传输过程中是否发生了改变。CRC算法通过计算一个固定长度的校验码&#xff0c;将该校验码附加到原…

Linux:进程

先了解一下这篇的基础知识 操作系统简述-CSDN博客还有这篇 ok我们来说进程 进程是什么&#xff1f; 在Windows下我们按下EscCtrlShift召唤任务管理器&#xff0c;查看Windows下的进程 我们的进程也是由操作系统管理的&#xff0c;操作系统对进程的管理也是先描述再组织。 …

Docker Hub 镜像代理加速

因为未知原因&#xff0c;docker hub 已经不能正常拉取镜像&#xff0c;可以使用以下代理服务来进行&#xff1a; "https://docker.m.daocloud.io", "https://noohub.ru", "https://huecker.io", "https://dockerhub.timeweb.cloud"…

更深层的理解视觉Transformer, 对视觉Transformer的剖析

写在前面&&笔者的个人理解 目前基于Transformer结构的算法模型已经在计算机视觉&#xff08;CV&#xff09;领域展现出了巨大的影响力。他们在很多基础的计算机视觉任务上都超过了之前的卷积神经网络&#xff08;CNN&#xff09;算法模型&#xff0c;下面是笔者找到的…