qt中网络判断有三种方式:
1.调用系统提供的dbus接口:org.freedesktop.NetworkManager,存在缺点:在Linux环境返回的状态有问题,而且状态变化时反应很慢。
2.qt自己的库,缺点也是反应慢,不能及时捕捉告知网络状态的变化。
QNetworkConfigurationManager ×m_pNetCfgMgr = new QNetworkConfigurationManager(this); //分配空间 //判断初始的网络状态
qDebug() << "------" << m_pNetCfgMgr->isOnline();
3.访问指定的服务器。
1)通过QHostInfo访问指定的服务器,缺点还是状态变化反应很慢(测试是切换系统的网络开关);
2)连接指定的服务器,因为有没有外网及网络状态好不好是要通过数据流进行判断,自己可以封装个类通过http请求指定的服务器,根据返回状态来判断情况;
connect(m_Timer, &QTimer::timeout, this, [=] ()
{
NetworkConnectivityCheck networkCheck(this);
int baiduStatus = -1;
if (!networkCheck.m_isEnter)
baiduStatus = networkCheck.getNetworkStatus(BaiduHostName);
if (CheckNetworkState::NetworkNormal == baiduStatus)
{
qDebug() << "baidu is ok";
return true;
}
int bingStatus = -1;
if (!networkCheck.m_isEnter)
bingStatus = networkCheck.getNetworkStatus(BingHostName);
if ((CheckNetworkState::NetworkNormal == bingStatus)
|| (CheckNetworkState::NetworkConnectionTimeout == baiduStatus
&& CheckNetworkState::NetworkConnectionTimeout == bingStatus)
/*|| networkCheck.getNetWorkInterfaceStatus()*/)
{
qDebug() << "bing is ok";
return true;
}
qDebug() << "Current local network exception.";
return false;
});
下面为自己封装的类:
#ifndef NETWORKCONNECTIVITYCHECK_H
#define NETWORKCONNECTIVITYCHECK_H
#include <QObject>
#include <QEventLoop>
#include <QNetworkReply>
#include <QNetworkAccessManager>
enum CheckNetworkState {
NetworkNormal,
NetworkConnectionTimeout,
NoNetwork
};
class NetworkConnectivityCheck : public QObject
{
Q_OBJECT
public:
explicit NetworkConnectivityCheck(QObject *parent = nullptr);
~NetworkConnectivityCheck();
int getNetworkStatus(QString url);
bool getNetWorkInterfaceStatus();
QEventLoop m_synchronous;
public slots:
void quitEventLoop();
public:
bool m_isEnter;
private:
QNetworkAccessManager m_networkManager;
QNetworkReply *m_reply;
};
#endif // NETWORKCONNECTIVITYCHECK_H
#include "networkconnectivitycheck.h"
#include <QScopedPointer>
#include <QTimer>
#include <QNetworkInterface>
NetworkConnectivityCheck::NetworkConnectivityCheck(QObject *parent)
: QObject(parent)
, m_isEnter(false)
, m_reply(nullptr)
{
connect(&m_networkManager, &QNetworkAccessManager::finished, this,
&NetworkConnectivityCheck::quitEventLoop);
}
NetworkConnectivityCheck::~NetworkConnectivityCheck()
{
if (m_reply) {
m_reply->abort();
m_reply->deleteLater();
m_reply = nullptr;
}
quitEventLoop();
}
int NetworkConnectivityCheck::getNetworkStatus(QString url)
{
m_isEnter = true;
m_reply = m_networkManager.get(QNetworkRequest(QUrl(url)));
qDebug() << "Connecting to url:" << url;
qDebug() << "QNetworkReply error:" << m_reply->errorString();
QTimer *checkNetwork = new QTimer(this);
bool isResult = false;
int connectStatus = -1;
checkNetwork->start(500);
connect(checkNetwork, &QTimer::timeout, [&]() {
if (!isResult) {
checkNetwork->stop();
qDebug() << "check network timeout 500ms.";
connectStatus = CheckNetworkState::NetworkConnectionTimeout;
quitEventLoop();
}
});
m_synchronous.exec();
if (CheckNetworkState::NetworkConnectionTimeout != connectStatus) {
checkNetwork->stop();
m_reply->close();
if (m_reply->error() == QNetworkReply::NoError
&& m_reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt() == 200) {
qDebug() << "Connected to url:" << url << " success!";
if (connectStatus == -1)
connectStatus = CheckNetworkState::NetworkNormal;
} else {
qDebug() << "To connect url:" << url << " failed!";
qDebug() << "QNetworkReply error:" << m_reply->errorString();
if (connectStatus == -1)
connectStatus = CheckNetworkState::NoNetwork;
}
isResult = true;
}
m_isEnter = false;
return connectStatus;
}
bool NetworkConnectivityCheck::getNetWorkInterfaceStatus()
{
QList<QNetworkInterface> networkList = QNetworkInterface::allInterfaces();
bool isConnect = false;
for (auto interface : networkList) {
if (interface.isValid()) {
//返回与此网络接口关联的标志。
QNetworkInterface::InterfaceFlags flags = interface.flags();
qDebug() << "flags: " << flags;
qDebug() << "name: " << interface.name();
if (flags.testFlag(QNetworkInterface::IsUp) && flags.testFlag(QNetworkInterface::IsRunning)
&& !flags.testFlag(QNetworkInterface::IsLoopBack)) {
isConnect = true;
qDebug() << "get local network status is:" << isConnect;
}
}
}
return isConnect;
}
void NetworkConnectivityCheck::quitEventLoop()
{
if (m_synchronous.isRunning())
m_synchronous.quit();
}
4.底层封装网络判断接口。
总结:在和服务器进行数据交互时,优先判断网络情况(是否有外网,网络状况是否良好[是否存在弱网的环境]),然后判断服务器的联通和数据交互情况,如果是弱网就要考虑超时的情况,一般自己设置超时时间,屏蔽https的超时,具体还是根据实际的项目需要吧。