Qt 之检测程序是否连外网

2021/4/11 14:27:28

本文主要是介绍Qt 之检测程序是否连外网,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

背景

项目交互中,经常要用到websocket,http与服务器通信,但是网络情况又没法保证,网络可能一会是链接状态,一会是断开状态,所以需要有能力实时去检测网络状态;传统方法,或者要求行不高的情况下,大多采取程序中单独去个线程,去定时获取外网是否联通。但在商业项目中,尤其是toc的行业,这种网络检测一定要稳定、靠谱,不然直接会给商品大打折扣。
本项目,刚开始也是采用了传统的方法开个网络检测线程,但后来跟人沟通,这种方法不适合,比如在电脑端,如果10个程序都需要联网呢?难道需要10个app都要开线程去检测嘛。所以,网络检测应该时系统层面链路层的东西。
下面简单介绍下传统检测的两种方法,直接给代码了!

使用QNetworkAccessManager / post

.h

class NetLiveWorker : public QObject
{
    Q_OBJECT
public:
    explicit NetLiveWorker(QObject *parent = nullptr);
    ~NetLiveWorker();
    Q_INVOKABLE bool getLive(){return m_isLive;}
    Q_INVOKABLE bool IsHostOnline(QString strHostName, int nTimeoutmSeconds = 2000);
    bool IsWebOk();

signals:
    void sig_netChanged(bool);
public slots:
    void onTimeout();

private:
    bool m_isLive;
    bool m_isFirst;
    QNetworkAccessManager *pmanager;
};

.cpp

NetLiveWorker::NetLiveWorker(QObject *parent) : QObject(parent)
{
    m_isFirst = true;
    m_isLive = false;
    pmanager = new QNetworkAccessManager(this);
}

NetLiveWorker::~NetLiveWorker()
{
    if(pmanager)
        delete  pmanager;
    pmanager = NULL;
}

bool NetLiveWorker::IsWebOk()
{
    //return IsHostOnline("110.242.68.4", 2000);
    return IsHostOnline("https://www.baidu.com/", 3000);
}

void NetLiveWorker::onTimeout()
{
    bool islive = IsWebOk();
    //qDebug()<<"Worker::onTimeout islive =" << islive << "m_islive=" << m_isLive;
    if(m_isLive != islive || m_isFirst)
    {
        emit sig_netChanged(islive);
    }
    m_isLive = islive;
    m_isFirst = false;
    //qDebug()<<"Worker::onTimeout get called from : "<<QThread::currentThreadId() << m_isLive;
}

bool NetLiveWorker::IsHostOnline(QString strHostName, int nTimeoutmSeconds)
{
    QNetworkRequest request(strHostName);
    request.setRawHeader("Content-Type", "charset='utf-8'");
    request.setRawHeader("Content-Type", "application/json");


    QEventLoop eventloop;

    QTimer timer;
    timer.singleShot(nTimeoutmSeconds, &eventloop, SLOT(quit()));
    timer.start();

    QNetworkReply* reply = pmanager->get(request);
    QMetaObject::Connection conRet = QObject::connect(reply, SIGNAL(finished()), &eventloop, SLOT(quit()));
    Q_ASSERT(conRet);

    eventloop.exec(QEventLoop::ExcludeUserInputEvents);

    if (!timer.isActive())
    {
        //超时,未知状态
        QObject::disconnect(reply, SIGNAL(finished()), &eventloop, SLOT(quit()));
        reply->abort();
        reply->deleteLater();

        return false;
    }

    if (reply->error() != QNetworkReply::NoError)
    {
        //qDebug() << "error = " <<reply->error();
        reply->abort();
        reply->deleteLater();
        return false;
    }

    bool bRes = reply->readAll().length() > 0;
    reply->abort();
    reply->deleteLater();

    return bRes;
}

使用getlive方法即可拿到当前外网状态。

ping命令实现

.h

class NetworkDetect : public QThread
{
    Q_OBJECT
public:
    NetworkDetect();

    virtual void run();
    void stop();
signals:
    void sig_netStatusChanged(bool state);

private:
    bool flagRunning;   //线程运行标志
    QProcess *network_process;

};

.cpp

NetworkDetect::NetworkDetect()
{
    flagRunning = true;
}


void NetworkDetect::run()
{
    QString network_cmd = "ping www.baidu.com -w 500 -n 2";
    QString result;
    network_process = new QProcess();    //不要加this
    while(flagRunning)
    {
        network_process->start(network_cmd);   //调用ping 指令
        network_process->waitForFinished();    //等待指令执行完毕
        result = network_process->readAll();   //获取指令执行结果
        //qDebug() << result;
        if(result.contains(QString("TTL=")) || result.contains(QString("ttl=")))   //若包含TTL=字符串则认为网络在线
        {
            emit sig_netStatusChanged(true);  //在线
        }
        else
        {
            emit sig_netStatusChanged(false); //离线
        }
        sleep(1);  //加sleep降低CPU占用率
    }
}

void NetworkDetect::stop()
{
    flagRunning = false;
}

不同平台下ping命令的参数不一样,可通过 ping --help来参考

扩展

在某些嵌入式平台下,应该时系统层面通过回调函数来告诉你外网是否联通,有种wifi情况下,即使通知你链接成功了,也未必能通外网,还是需要你通过portalAuth机制来检测下。即拿到网络链路成功后,通过http或者ping方法确实是否能连外网。

Portal认证简介
Portal认证通常也称为Web认证,一般将Portal认证网站称为门户网站。用户上网时,必须在门户网站进行认证,只有认证通过后才可以使用网络资源。

用户可以主动访问已知的Portal认证网站,输入用户名和密码进行认证,这种开始Portal认证的方式称作主动认证。反之,如果用户试图通过HTTP访问其他外网,将被强制访问Portal认证网站,从而开始Portal认证过程,这种方式称作强制认证。

内置portal认证---------指的就是会话认证。
外置Portal认证



这篇关于Qt 之检测程序是否连外网的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!


扫一扫关注最新编程教程