QNetworkConfiguration 表示网络连接配置,例如到特定接入点的 Wi-Fi 连接,其服务集标识符 (SSID) 作为配置名称。
网络配置可以是以下类型之一:
QNetworkConfiguration::InternetAccessPoint:
这种类型是典型的接入点,例如 Wi-Fi 接入点 (AP),也可以代表以太网或移动网络。
QNetworkConfiguration::ServiceNetwork:
ServiceNetwork 类型是一组称为服务网络访问点 (SNAP) 的访问点。系统将根据成本、速度和可用性等标准确定最适合连接的服务网络。 QNetworkConfiguration::ServiceNetwork 类型的配置也可以在其子 QNetworkConfiguration::InternetAccessPoint 之间漫游。
QNetworkConfiguration::UserChoice:
这种类型可以代表用户首选的配置。它被诺基亚的 Maemo 和 Symbian 平台使用,系统可以在其中弹出一个对话框,要求用户选择最好的 AP。当前的承载后端都没有使用这种类型的 QNetworkConfiguration。
通常,我们需要知道承载的类型,也就是说,连接使用的是什么通信协议。让我们了解一下 BearerType。
QNetworkConfiguration::BearerType
这是一个枚举,指定 QNetworkConfiguration 的底层技术是什么,可以是以下之一:
BearerEthernet
BearerWLAN
Bearer2G
BearerCDMA2000
BearerWCDMA
BearerHSPA
BearerBluetooth
BearerWiMAX
BearerEVDO
BearerLTE
Bearer3G
Bearer4G
这可以通过调用 QNetworkConfiguration 对象的 bearerType() 函数来确定,如下所示:
QNetworkConfiguration 配置;您可以打开或连接。
QNetworkConfiguration config;
if (config.bearerType() == QNetworkConfiguration::Bearer4G)
qWarning() << "Config is using 4G";
QNetworkConfiguration::StateFlags
StateFlags 是一个 OR’d ||,StateFlag 值的组合,如下所示:
Defined:系统已知但尚未配置
Discovered:已知并配置,可用于open()
Active:目前在线
具有 Active 标志的 QNetworkConfiguration 也将具有 Discovered 和 Defined 标志。 您可以通过执行以下操作来检查配置是否处于活动状态:
QNetworkConfiguration config;
if (config.testFlag(QNetworkConfiguration::Active))
qWarning() << "Config is active";
网络配置管理器
QNetworkConfigurationManager 允许您获取系统的 QNetworkConfigurations,如下所示:
QNetworkConfigurationManager manager;
QNetworkConfiguration default = manager.defaultConfiguration();
在使用之前等待来自 QNetworkConfigurationManager 的 updateCompleted 信号总是明智的,以确保配置设置正确。
默认配置是系统定义为默认的配置。它的状态可能是 Active 或只是 Discovered。
如果需要简单判断系统当前是否在线,manager->isOnline();如果系统被认为在线,将返回 true。在线是指它通过网络连接到另一台设备,该网络可能是也可能不是互联网,并且可能会或可能不会正确路由。所以,它可以在线,但不能访问互联网。
您可能需要调用 updateConfigurations(),它会要求系统更新配置列表,然后您需要在继续之前监听 updateCompleted 信号。
您可以通过调用 allConfigurations() 获取系统已知的所有配置,或者使用 allConfigurations(QNetworkConfiguration::Discovered); 将其过滤为具有特定状态的配置。
在这种情况下,它返回已发现配置的列表。
CanStartAndStopInterfaces:系统允许用户启动和停止连接
DirectConnectionRouting:连接路由直接绑定到指定的设备接口
SystemSessionSupport:系统保持连接打开,直到所有会话都关闭
ApplicationLevelRoaming:应用程序可以控制漫游/迁移
ForcedRoaming:漫游/迁移时系统将重新连接
DataStatics:系统提供有关传输和接收数据的信息
NetworkSessionRequired:系统需要一个会话
NetworkSession 提供了一种启动和停止连接以及提供连接会话管理的方法。在使用 ServiceNetwork 类型的 QNetworkConfiguration 实例化 QNetworkSession 的情况下,它可以提供漫游功能。在大多数系统上,漫游将需要实际断开连接,然后连接新的接口和/或连接。在其他情况下,漫游可以是无缝的并且不会干扰用户的数据流。
如果 QNetworkConfigurationManager 的功能报告它支持 CanStartAndStopInterfaces,那么您使用 QNetworkSession 来 open()(连接)和 stop()(关闭)QNetworkConfigurations。
mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QNetworkSession>
#include <QNetworkConfigurationManager>
#include <QNetworkReply>
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = nullptr);
~MainWindow();
private:
Ui::MainWindow *ui;
QNetworkAccessManager *accessMan;
//QNetworkConfiguration 表示网络连接配置,例如到特定接入点的 Wi-Fi 连接,其服务集标识符 (SSID) 作为配置名称。
QNetworkConfigurationManager *configMan;
QString stateToString(QNetworkSession::State state);
void printCaps(QNetworkConfigurationManager::Capabilities);
private slots:
void stateChanged(QNetworkSession::State state);
void finished(QNetworkReply *reply);
void opened();
void updateCompleted();
};
#endif // MAINWINDOW_H
mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QNetworkAccessManager>
#include <QNetworkConfiguration>
#include <QNetworkConfigurationManager>
#include <QNetworkSession>
#include <QNetworkRequest>
#include <QNetworkReply>
#include <QObject>
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
//QNAM 在后台发出网络请求时将使用 QNetworkSession。您可以使用 QNetworkSession 来监视连接,如下所示
accessMan = new QNetworkAccessManager(this);
QObject::connect(accessMan, &QNetworkAccessManager::finished,
this, &MainWindow::finished);
qWarning() << "network accessible" << accessMan->networkAccessible();
configMan = new QNetworkConfigurationManager(this);
connect(configMan, &QNetworkConfigurationManager::updateCompleted,
this, &MainWindow::updateCompleted);
//如果需要简单判断系统当前是否在线,manager->isOnline();如果系统被认为在线,将返回 true。在线是指它通过网络连接到另一台设备,该网络可能是也可能不是互联网,并且可能会或可能不会正确路由。所以,它可以在线,但不能访问互联网。
qWarning() << "isOnline?" << configMan->isOnline();
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::stateChanged(QNetworkSession::State state)
{
qDebug() << Q_FUNC_INFO << stateToString(state);
}
QString MainWindow::stateToString(QNetworkSession::State state)
{
switch (state) {
case QNetworkSession::NotAvailable:
return QStringLiteral("NotAvailable");
break;
case QNetworkSession::Connected:
return QStringLiteral("Connected");
break;
case QNetworkSession::Connecting:
return QStringLiteral("Connecting");
break;
case QNetworkSession::Closing:
return QStringLiteral("Closing");
break;
case QNetworkSession::Disconnected:
return QStringLiteral("Disconnected");
break;
case QNetworkSession::Roaming:
return QStringLiteral("NotAvailable");
break;
default:
break;
};
return "Invalid";
}
void MainWindow::printCaps(QNetworkConfigurationManager::Capabilities caps)
{
if (caps.testFlag(QNetworkConfigurationManager::CanStartAndStopInterfaces))
qWarning() << "CanStartAndStopInterfaces";
if (caps.testFlag(QNetworkConfigurationManager::DirectConnectionRouting))
qWarning() << "DirectConnectionRouting";
if (caps.testFlag(QNetworkConfigurationManager::SystemSessionSupport))
qWarning() << "SystemSessionSupport";
if (caps.testFlag(QNetworkConfigurationManager::ApplicationLevelRoaming))
qWarning() << "ApplicationLevelRoaming";
if (caps.testFlag(QNetworkConfigurationManager::ForcedRoaming))
qWarning() << "ForcedRoaming";
if (caps.testFlag(QNetworkConfigurationManager::DataStatistics))
qWarning() << "DataStatistics";
if (caps.testFlag(QNetworkConfigurationManager::NetworkSessionRequired))
qWarning() << "NetworkSessionRequired";
if (caps.testFlag(QNetworkConfigurationManager::CanStartAndStopInterfaces))
qWarning() << "CanStartAndStopInterfaces";
}
void MainWindow::finished(QNetworkReply *reply)
{
if (reply->error() == QNetworkReply::NoError)
qWarning() << Q_FUNC_INFO;//<< reply->readAll();
else
qWarning() << Q_FUNC_INFO << reply->errorString();
}
void MainWindow::opened()
{
qWarning() << Q_FUNC_INFO;
QNetworkRequest request(QUrl("http://example.com"));
accessMan->get(request);
}
void MainWindow::updateCompleted()
{
qWarning() << "isOnline?" << configMan->isOnline();
qWarning() << "network accessible" << accessMan->networkAccessible();
printCaps(configMan->capabilities());
QNetworkConfiguration configuration = accessMan->configuration();
qWarning() << configuration.name() << configuration.state();
qDebug() <<"activeConfiguration"<< accessMan->activeConfiguration().name();
qDebug() <<"defaultConfiguration"<< configMan->defaultConfiguration().name();
QNetworkSession *session = new QNetworkSession(configuration, this);
qWarning() << stateToString(session->state());
connect(session, &QNetworkSession::stateChanged, this, &MainWindow::stateChanged);
connect(session, &QNetworkSession::opened, this, &MainWindow::opened);
if (session->isOpen()) {
opened();
} else {
qWarning() << "opening";
session->open();
}
}