最近研究了下 QT 如何访问网络,做一些简单总结。

首先在 pro 文件内定义网络属性:

QT  += network

如果需要连接 https 需要安装 openssl 工具,使用 QT 的 MaintenanceTool 工具找到 openssl toolkit 并安装。否则执行程序时 ssl 会报错。

安装后需要将 openssl 路径加入系统 PATH,默认安装路径为:Qt/Tools/OpenSSL。根据需要将对应系统版本的 bin 路径加入 PATH 如:C:\Qt\Tools\OpenSSL\Win_x86\bin,里面包含相关 lib 库文件。添加方法参考:https://blog.niekun.net/archives/413.html

需要用到的 QT class:
QNetworkAccessManager
QNetworkRequest
QSslConfiguration
QNetworkReply

我们做一个示例,新建项目,在头文件添加相关引用:

#include <QNetworkAccessManager>
#include <QNetworkReply>

public 栏添加触发网络访问的 function:

public:
    void doRequest();

private 栏定义指针:

private:
    QNetworkAccessManager *manager;

添加 private slots 用来处理服务器的回应:

private slots:
    void replyFinished(QNetworkReply *reply);

传入参数 reply 用来接收网络访问响应内容,对应于 signal: void QNetworkAccessManager::finished(QNetworkReply *reply),signal 触发后的数据通过 connect 会自动传入 slot 中,下面在源文件中做详细定义。

下面修改源文件,先在构造器中调用触发网络 function: doRequest()

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    doRequest();
}

下面实现 doRequest() 的内容:

void MainWindow::doRequest() {
    manager = new QNetworkAccessManager(this);

    QSslConfiguration sSlConfig;
    sSlConfig.setDefaultConfiguration(QSslConfiguration::defaultConfiguration());
    sSlConfig.setProtocol(QSsl::TlsV1_2);

    QNetworkRequest request;
    request.setSslConfiguration(sSlConfig);
    request.setUrl(QUrl("https://info.niekun.net"));
    request.setRawHeader("User-Agent", "MyOwnBrowser 1.0");

    manager->get(request);

    connect(manager, &QNetworkAccessManager::finished, this, &MainWindow::replyFinished);
    connect(manager, &QNetworkAccessManager::finished, manager, &QNetworkAccessManager::deleteLater);
}

首先实例化一个 QNetworkAccessManager 用来访问网络。

然后构造我们的 request 和 ssl 的初始化内容,request 中设置了访问的网络地址,定义了一个 request 的 header。

QNetworkAccessManager 的 object 使用 get function 来启动网络请求。

然后我们使用 connect 根据网络请求发出后的响应来触发相关 slot function。signal 触发后的数据会传入 slot function 中。所以 signal:void QNetworkAccessManager::finished(QNetworkReply *reply) 触发后返回的数据 reply 自动作为传入数据给 replyFinished

第二个 connect 的作用是网络请求结束后释放相关内存,避免造成内存溢出。

注意这里我使用了新版的 QT connect 语法,详细参考官方文档:https://wiki.qt.io/New_Signal_Slot_Syntax

下面实现 replyFinished:

void MainWindow::replyFinished(QNetworkReply *reply) {
    if(reply->error())
    {
        qDebug() << "ERROR!";
        qDebug() << reply->errorString();
    }
    else
    {
        qDebug() << reply->header(QNetworkRequest::ContentTypeHeader).toString();
        qDebug() << reply->header(QNetworkRequest::LastModifiedHeader).toDateTime().toString();;
        qDebug() << reply->header(QNetworkRequest::ContentLengthHeader).toULongLong();
        qDebug() << reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
        qDebug() << reply->attribute(QNetworkRequest::HttpReasonPhraseAttribute).toString();
        qDebug() << "-----------------------";
        qDebug().noquote() << reply->readAll();
    }
}

reply 指向 &QNetworkAccessManager::finished 的 QNetworkReply 数据。

在此 function 中,我们输出 reply 中的部分信息来检测网络是否通畅。其他的可用类型可以查询:https://doc.qt.io/qt-5/qnetworkrequest.html#public-types

注意使用 qDebug().noquote() 来自动将字符串中的 \n 作为换行处理。

正常输出信息如下:

"text/plain"
""
0
200
"OK"
-----------------------
request info:
request: GET / HTTP/1.1
scheme: https
host: info.niekun.net
http_host: info.niekun.net
uri: /
request_uri: /
connection: 202130
remote_addr: 172.68.189.53
client_real_ip: 1.81.217.183
server_port: 443

other variates:
http_x_forwarded_for: 1.81.217.183
proxy_add_x_forwarded_for: 1.81.217.183, 172.68.189.53

以上就是 QT 访问网络的简单教程。

参考链接:
https://www.bogotobogo.com/Qt/Qt5_Downloading_Files_QNetworkAccessManager_QNetworkRequest.php

标签:无

你的评论