基于ICMP(Ping)的多线程网络通道监视程序(QT)开发
1、 ICMP原理简介
可参考 ICMP(Ping)功能原理及其C++实现简介 。
2、 网络通道监视程序开发
设计原理: 通过PING
功能实现服务器、交换机、网闸等设备的网络检测,判断网络的否可达和TTL
计算 。
具备功能:
- 通过多线程,实现多个网络通道同时检测;
- 支持动态加包。
- 支持设置网络延迟阈值,超过阈值时提示用户。
①、 界面设计
程序采用QT开发,UI界面如下图所示:
中心区域为 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[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 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[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帧获取TTL
ttl = ucRxBuf[8];
//跳过IP Header 20个字节
uint8* pIcmpFrame = ucRxBuf + 20;
//Type和Code
uint8 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;
}
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[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 8
CHostInfoArray 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[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++;
}
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[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)); //超限,红色提示
else
ui->tableWidget->item(k, 3)->setBackgroundColor(QColor(255, 255, 255));
}
if (pPingInfo[n].attl < 0)
ui->tableWidget->item(k, 4)->setText(QString("---"));
else
ui->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)); //超限,红色提示
else
ui->tableWidget->item(k, 5)->setBackgroundColor(QColor(255, 255, 255));
}
if (pPingInfo[n].bttl < 0)
ui->tableWidget->item(k, 6)->setText(QString("---"));
else
ui->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);
}