ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

Qt 之检测程序是否连外网

2021-04-11 13:00:34  阅读:346  来源: 互联网

标签:Qt Portal 检测 void 连外 认证 bool reply NetLiveWorker


背景

项目交互中,经常要用到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,Portal,检测,void,连外,认证,bool,reply,NetLiveWorker
来源: https://blog.csdn.net/u011942101/article/details/115595578

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有