在程序涉及到联网时,总是需要检测网络状态。而最直接、有效的网络状态检测方法就是使用ping命令。我们通常判断网络是否通畅,会使用ping www.baidu.com 之类的命令。
网上有许多判断网络状态的例子,比如:
QHostInfo::lookupHost("www.baidu.com",this,SLOT(onLookupHost(QHostInfo)));
void CommonParameter::onLookupHost(QHostInfo host)
{
if (host.error() != QHostInfo::NoError) {
qDebug() << "Lookup failed:" << host.errorString();
emit sigLookUpHostResult(false); //离线
}
else
{
emit sigLookUpHostResult(true); //在线
}
}
但是该方法,离线后需要一段时间才能判断出来。并且在DNS解析成功后就会显示在线,实际上电脑并不能上网。(实测,在公司禁外网的情况下,检测状态仍为在线)
纠结了这么久,个人认为最简单、直接的判断网络状态的方法是,通过QProcess系统调用ping指令,再根据执行结果是否包含特殊字符串来判断网络状态。但是ping指令执行完毕需要耗时几秒,这样会导致检测实时性不强。这就需要研究ping指令的具体用法了。
如下为windows中ping命令的用法:
其中 -n 为请求数,-w 为请求超时时间。为了更快获取网络状态结果,调整这两个参数即可。例如:
ping www.baidu.com -n 2 -w 500
其含义为向www.baidu.com请求两包数据,每包数据超时时间为500ms。系统调用这个命令,就能在1s内获取网络状态了。但是如果在主线程中直接调用该指令,会存在阻塞,导致界面卡顿。所以,建议通过线程来调用ping指令。
如下为自己写的示例程序,供大家参考,若有问题还请大佬多多指正:
network_detect.h
#ifndef NETWORK_DETECT_H
#define NETWORK_DETECT_H
#include <QProcess>
#include <QThread>
class network_detect : public QThread
{
Q_OBJECT //一定要加这个
public:
network_detect();
virtual void run();
void stop();
signals:
void send_network_connect_state(int state);
private:
bool flagRunning; //线程运行标志
QProcess *network_process;
};
#endif // NETWORK_DETECT_H
network_detect.cpp
#include "network_detect.h"
network_detect::network_detect()
{
flagRunning = true;
}
void network_detect::run()
{
QString network_cmd = "ping www.baidu.com -n 2 -w 500";
QString result;
network_process = new QProcess(); //不要加this
while(flagRunning)
{
network_process->start(network_cmd); //调用ping 指令
network_process->waitForFinished(); //等待指令执行完毕
result = network_process->readAll(); //获取指令执行结果
if(result.contains(QString("TTL="))) //若包含TTL=字符串则认为网络在线
{
emit send_network_connect_state(1); //在线
}
else
{
emit send_network_connect_state(0); //离线
}
sleep(1); //加sleep降低CPU占用率
}
}
void network_detect::stop()
{
flagRunning = false;
}
widget.h
#ifndef WIDGET_H
#define WIDGET_H
#include <QWidget>
#include "network_detect.h" //包含头文件
namespace Ui {
class Widget;
}
class Widget : public QWidget
{
Q_OBJECT
public:
explicit Widget(QWidget *parent = 0);
~Widget();
public slots:
void update_network_state(int state); //更新网络状态
private:
Ui::Widget *ui;
network_detect *detect_thread;
};
#endif // WIDGET_H
widget.cpp
#include "widget.h"
#include "ui_widget.h"
Widget::Widget(QWidget *parent) :
QWidget(parent),
ui(new Ui::Widget)
{
ui->setupUi(this);
detect_thread = new network_detect();
connect(detect_thread, SIGNAL(send_network_connect_state(int)), this, SLOT(update_network_state(int)));
detect_thread->start(); //开启网络检测线程
}
Widget::~Widget()
{
delete ui;
}
void Widget::update_network_state(int state)
{
if(state)
ui->label->setText("在线");
else
ui->label->setText("离线");
}
程序运行结果:
程序能够迅速检测网络状态,并显示出来,网络正常时,显示结果如下:
网络异常或拔掉网线后,最多2s内能检测到离线,如下所示: