首页 > 编程语言 >C++ Qt开发:QNetworkAccessManager网络接口组件

C++ Qt开发:QNetworkAccessManager网络接口组件

时间:2024-03-12 12:55:26浏览次数:29  
标签:QNetworkRequest const Qt QByteArray 网络 C++ QNetworkReply 请求 网络接口

Qt 是一个跨平台C++图形界面开发库,利用Qt可以快速开发跨平台窗体应用程序,在Qt中我们可以通过拖拽的方式将不同组件放到指定的位置,实现图形化开发极大的方便了开发效率,本章将重点介绍如何运用QNetworkAccessManager组件实现Web网页访问。

QNetworkAccessManager是Qt网络模块中的关键类,用于管理网络访问和请求。作为一个网络请求的调度中心,它为Qt应用程序提供了发送和接收各种类型的网络请求的能力,包括常见的GET、POST、PUT、DELETE等。这个模块的核心功能在于通过处理QNetworkReplyQNetworkRequest来实现与网络资源的交互。

通过QNetworkAccessManager,Qt应用程序能够轻松地与远程服务器通信,获取数据或将数据上传到服务器。这种网络请求的管理不仅是异步的,以确保不会阻塞主线程,还提供了丰富的信号和槽机制,使得开发者可以灵活地处理不同阶段的网络操作。

通常,QNetworkAccessManager会与QNetworkReplyQNetworkRequest一起使用。QNetworkRequest用于封装和配置网络请求的各种属性,例如URL、请求头等。而QNetworkReply则代表了对网络请求的响应,包含了请求返回的数据和相关信息。这三者共同协作,为Qt应用程序提供了便捷、灵活且强大的网络通信能力。

1.1 通用API函数

1.1.1 QNetworkAccessManager

要想实现网络通信首先需要新建一个网络访问管理器,以下是QNetworkAccessManager类中的一些常用函数及其描述:

函数 描述
QNetworkAccessManager(QObject *parent = nullptr) 构造函数,创建一个QNetworkAccessManager实例。
virtual ~QNetworkAccessManager() 虚析构函数,释放QNetworkAccessManager实例。
QNetworkReply *get(const QNetworkRequest &request) 发送GET请求,并返回与请求关联的QNetworkReply对象。
QNetworkReply *post(const QNetworkRequest &request, QIODevice *data) 发送POST请求,并返回与请求关联的QNetworkReply对象。
QNetworkReply *post(const QNetworkRequest &request, const QByteArray &data) 发送POST请求,并返回与请求关联的QNetworkReply对象。
QNetworkReply *put(const QNetworkRequest &request, QIODevice *data) 发送PUT请求,并返回与请求关联的QNetworkReply对象。
QNetworkReply *put(const QNetworkRequest &request, const QByteArray &data) 发送PUT请求,并返回与请求关联的QNetworkReply对象。
QNetworkReply *deleteResource(const QNetworkRequest &request) 发送DELETE请求,并返回与请求关联的QNetworkReply对象。
QNetworkReply *head(const QNetworkRequest &request) 发送HEAD请求,并返回与请求关联的QNetworkReply对象。
QNetworkReply *sendCustomRequest(const QNetworkRequest &request, const QByteArray &verb, QIODevice *data = nullptr) 发送自定义请求,并返回与请求关联的QNetworkReply对象。
QNetworkReply *sendCustomRequest(const QNetworkRequest &request, const QByteArray &verb, const QByteArray &data) 发送自定义请求,并返回与请求关联的QNetworkReply对象。
void setConfiguration(const QNetworkConfiguration &config) 设置网络配置,用于定制网络行为。
QNetworkConfiguration configuration() const 获取当前网络配置。
void clearAccessCache() 清除网络访问缓存。
void setCache(QAbstractNetworkCache *cache) 设置网络缓存。
QAbstractNetworkCache *cache() const 获取当前网络缓存。
void setCookieJar(QNetworkCookieJar *cookieJar) 设置用于管理HTTP cookie的QNetworkCookieJar
QNetworkCookieJar *cookieJar() const 获取当前的HTTP cookie管理器。

这些函数提供了QNetworkAccessManager的核心功能,使得开发者能够方便地进行各种类型的网络请求,配置网络参数,并进行相关的网络管理操作。

1.1.2 QNetworkReply

以下是QNetworkReply类中的一些常用函数及其描述:

函数 描述
QByteArray readAll() const 读取所有可用的数据,并返回一个QByteArray,包含从网络回复读取的所有内容。
QByteArray peek(int maxSize) const 查看最多maxSize字节的可用数据,但不从缓冲区中移除。
QByteArray read(int maxSize) 从网络回复中读取最多maxSize字节的数据,并将其从缓冲区中移除。
QByteArray readLine(int maxSize = 0) 从网络回复中读取一行数据,最多包含maxSize字节,并将其从缓冲区中移除。
void ignoreSslErrors(const QList<QSslError> &errors = QList<QSslError>()) 忽略SSL错误,继续处理网络回复。
void abort() 终止网络回复的处理,关闭底层连接。
void close() 关闭网络回复的处理。
QUrl url() const 返回与网络回复相关联的URL。
QNetworkRequest request() const 返回生成此网络回复的网络请求。
QNetworkAccessManager *manager() const 返回与网络回复相关联的QNetworkAccessManager
bool isFinished() const 检查网络回复是否已完成。
QNetworkReply::NetworkError error() const 返回网络回复的错误代码。
bool hasRawHeader(const QByteArray &headerName) const 检查网络回复是否包含指定原始头。
QList<QByteArray> rawHeaderList() const 返回网络回复的所有原始头的列表。
QByteArray rawHeader(const QByteArray &headerName) const 返回指定原始头的值。
QVariant header(QNetworkRequest::KnownHeaders header) const 返回指定标准头的值。
QList<QByteArray> rawHeaderValues(const QByteArray &headerName) const 返回指定原始头的所有值。
QVariant attribute(QNetworkRequest::Attribute code) const 返回指定网络请求属性的值。
QIODevice *readAllStandardOutput() 读取标准输出的所有数据,并返回一个QIODevice,用于访问读取的内容。
QIODevice *readAllStandardError() 读取标准错误的所有数据,并返回一个QIODevice,用于访问读取的内容。
bool isReadable() const 检查网络回复是否可读取。

这些函数提供了对QNetworkReply实例进行各种操作和查询的方法,包括读取回复数据、处理SSL错误、获取请求信息、检查错误状态等。开发者可以根据具体需求使用这些函数来有效地与网络回复进行交互。

1.1.3 QNetworkRequest

以下是QNetworkRequest类中的一些常用函数及其描述:

函数 描述
QNetworkRequest(const QUrl &url) 使用给定的URL构造一个QNetworkRequest实例。
void setUrl(const QUrl &url) 设置QNetworkRequest的URL。
QUrl url() const 返回与QNetworkRequest相关联的URL。
void setRawHeader(const QByteArray &headerName, const QByteArray &headerValue) 设置指定原始头的值。
QByteArray rawHeader(const QByteArray &headerName) const 返回指定原始头的值。
bool hasRawHeader(const QByteArray &headerName) const 检查QNetworkRequest是否包含指定原始头。
void setRawHeaderList(const QList<QByteArray> &headerList) 设置所有原始头的列表。
QList<QByteArray> rawHeaderList() const 返回QNetworkRequest的所有原始头的列表。
void setHeader(QNetworkRequest::KnownHeaders header, const QVariant &value) 设置指定标准头的值。
QVariant header(QNetworkRequest::KnownHeaders header) const 返回指定标准头的值。
void setAttribute(QNetworkRequest::Attribute code, const QVariant &value) 设置指定网络请求属性的值。
QVariant attribute(QNetworkRequest::Attribute code) const 返回指定网络请求属性的值。
void setSslConfiguration(const QSslConfiguration &config) 设置SSL配置。
QSslConfiguration sslConfiguration() const 返回SSL配置。
void setMaximumRedirectsAllowed(int maxRedirects) 设置允许的最大重定向次数。
int maximumRedirectsAllowed() const 返回允许的最大重定向次数。
void setOriginatingObject(QObject *object) 设置发起此网络请求的对象。
QObject *originatingObject() const 返回发起此网络请求的对象。
bool isEmpty() const 检查QNetworkRequest是否为空(未设置URL)。

这些函数提供了对QNetworkRequest实例进行各种操作和查询的方法,包括设置和获取头信息、设置SSL配置、设置和获取网络请求属性等。开发者可以根据具体需求使用这些函数来有效地构建和管理网络请求。

1.2 实现Web页面访问

要使用该模块读者应该在*.pro文件内包含network网络模块,并在头文件中引入QNetworkAccessManagerQNetworkReplyQNetworkRequest三个类,在建立访问时首先使用QNetworkAccessManager新增一个manager管理类,并通过QNetworkRequest类创建一个GET请求地址,通过使用manager.get方法实现对特定页面的访问。

当访问完成时需要通过一个信号来实现对数据的处理,在QNetworkReply类中包含有如下表所示的信号以供读者使用,例如当访问被完成时则自动触发&QNetworkReply::finished完成信号,此时只需要对该信号进行相应的处理即可,通常会使用一个槽函数来处理它。

信号 描述
finished() 当网络请求完成时发出。
downloadProgress(qint64, qint64) 在下载过程中定期发出,提供下载进度信息。参数为已下载的字节数和总字节数。
uploadProgress(qint64, qint64) 在上传过程中定期发出,提供上传进度信息。参数为已上传的字节数和总字节数。
readyRead() 当有可读取的数据时发出,用于通知应用程序可以调用readAll()read()方法以获取更多数据。
error(QNetworkReply::NetworkError) 当网络请求发生错误时发出,参数为错误代码。
sslErrors(const QList<QSslError> &) 当SSL错误发生时发出,参数为SSL错误的列表。

这些信号提供了丰富的信息,使开发者能够在不同阶段处理网络请求。同理,在下载和上传过程中可以使用downloadProgressuploadProgress信号来获取进度信息,readyRead信号表示有可读取的数据,error信号表示请求发生错误,sslErrors信号表示SSL相关的错误。

当信号被触发时则会通过QObject::connect连接到对应的槽函数上,如下案例中所示,在槽函数内通过reply->attribute方法我们获取到此次响应码中的QNetworkRequest::HttpStatusCodeAttribute属性,该属性用来指明本次访问的状态值。此类属性也有许多可供参考,如下所示;

属性 描述
QNetworkRequest::HttpStatusCodeAttribute HTTP响应的状态码。
QNetworkRequest::HttpReasonPhraseAttribute HTTP响应的原因短语,如"OK"、"Not Found"等。
QNetworkRequest::RedirectionTargetAttribute 重定向目标的URL。
QNetworkRequest::ConnectionEncryptedAttribute 连接是否加密的标志,返回一个bool值。
QNetworkRequest::SourceIsFromCacheAttribute 请求是否来自缓存的标志,返回一个bool值。
QNetworkRequest::HttpPipeliningAllowedAttribute 是否允许HTTP流水线传输的标志,返回一个bool值。
QNetworkRequest::HttpPipeliningWasUsedAttribute 是否使用了HTTP流水线传输的标志,返回一个bool值。
QNetworkRequest::CustomVerbAttribute 自定义请求动作(HTTP verb)的字符串。
QNetworkRequest::User 用户自定义的属性,用于存储任意类型的用户数据。

这些属性提供了额外的信息,使得开发者能够更全面地了解和处理网络响应。根据具体的应用需求,开发者可以选择使用这些属性中的一个或多个来获取所需的信息。

#include <QCoreApplication>
#include <QNetworkAccessManager>
#include <QNetworkReply>
#include <QNetworkRequest>
#include <QDebug>

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    // 创建网络访问管理器
    QNetworkAccessManager manager;

    // 创建GET请求
    QNetworkRequest request(QUrl("http://www.baidu.com"));

    // 发送GET请求
    QNetworkReply *reply = manager.get(request);

    // 连接信号槽,处理响应
    QObject::connect(reply, &QNetworkReply::finished, [&]()
    {
        if (reply->error() == QNetworkReply::NoError)
        {
            // 获取请求的 URL
            qDebug() << "Request URL:" << reply->request().url();

            // 输出请求头信息
            qDebug() << "Request Headers:";
            QList<QByteArray> requestHeaders = reply->request().rawHeaderList();
            foreach (const QByteArray &header, requestHeaders) {
                qDebug() << header << ":" << reply->request().rawHeader(header);
            }

            // 获取响应码
            int statusCode = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
            qDebug() << "HttpStatusCodeAttribute:" << statusCode;

            // 连接是否加密的标志
            bool connectionEncryptedAttribute = reply->attribute(QNetworkRequest::ConnectionEncryptedAttribute).toBool();
            qDebug() << "ConnectionEncryptedAttribute:" << connectionEncryptedAttribute;

            // 请求是否来自缓存的标志
            bool sourceIsFromCacheAttribute = reply->attribute(QNetworkRequest::SourceIsFromCacheAttribute).toBool();
            qDebug() << "SourceIsFromCacheAttribute:" << sourceIsFromCacheAttribute;

            // HTTP请求是否被允许进行流水线处理的标志
            bool httpPipeliningAllowedAttribute = reply->attribute(QNetworkRequest::HttpPipeliningAllowedAttribute).toBool();
            qDebug() << "HttpPipeliningAllowedAttribute:" << httpPipeliningAllowedAttribute;

            // 输出响应头信息
            qDebug() << "Response Headers:";
            QList<QByteArray> responseHeaders = reply->rawHeaderList();
            foreach (const QByteArray &header, responseHeaders) {
                qDebug() << header << ":" << reply->rawHeader(header);
            }

            // 处理响应内容,这里可以使用 readAll() 方法获取响应内容
            // qDebug() << "Response Content:" << reply->readAll();
        } else
        {
            qDebug() << "Error:" << reply->errorString();
        }

        // 释放资源
        reply->deleteLater();
        QCoreApplication::quit();
    });

    return a.exec();
}

读者可自行编译并运行这段代码,观察请求与相应数据如下图所示;

至于如何在图形界面中使用则就更简单了,首先我们在mainwindow.h头文件中定义好所需要的两个槽函数,函数on_finished()用于在完成请求后被调用,函数on_readyRead()则用于在回调被执行后调用,并并以两个网络管理类的指针变量,如下所示;

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    MainWindow(QWidget *parent = nullptr);
    ~MainWindow();

private slots:
    //自定义槽函数
    void on_finished();
    void on_readyRead();

    void on_pushButton_clicked();

private:
    Ui::MainWindow *ui;
    QNetworkAccessManager networkManager;   // 网络管理
    QNetworkReply *reply;                   // 网络响应
};

当获取按钮被点击后则开始执行读入指定URL地址,并对该地址进行网页访问,同时绑定这两个信号,一旦被触发则自动路由到对应的槽函数上面去,如下所示;

void MainWindow::on_pushButton_clicked()
{
    // 读入URL地址
    QString urlSpec = ui->lineEdit->text().trimmed();
    if (urlSpec.isEmpty())
    {
        QMessageBox::information(this, "错误", "请指定URL");
        return;
    }

    // 格式化URL
    QUrl newUrl = QUrl::fromUserInput(urlSpec);
    if (!newUrl.isValid())
    {
        QMessageBox::information(this, "错误", QString("无效URL: %1").arg(urlSpec));
        return;
    }

    // 访问页面
    reply = networkManager.get(QNetworkRequest(newUrl));

    // 完成时的槽函数绑定
    connect(reply, SIGNAL(finished()), this, SLOT(on_finished()));

    // 读入数据的槽函数绑定
    connect(reply, SIGNAL(readyRead()), this, SLOT(on_readyRead()));

}

相对应的,在on_finished()槽函数中我们将响应头读出并输出到文本框中,在on_readyRead()槽函数中则是对整个网站页面源代码的输出功能,完整代码如下所示;

void MainWindow::on_finished()
{
    // 获取响应码
    int statusCode = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();

    if(statusCode == 200)
    {
        ui->plainTextEdit_2->appendPlainText("响应头数据:");
        // 输出响应头信息
        QList<QByteArray> responseHeaders = reply->rawHeaderList();
        foreach (const QByteArray &header, responseHeaders)
        {
            ui->plainTextEdit_2->appendPlainText(header + " : " + reply->rawHeader(header));
        }
    }
}

// 读入页面源代码
void MainWindow::on_readyRead()
{
    ui->plainTextEdit->setPlainText(reply->readAll());
}

运行代码,读者可自行输入特定的网站进行读取测试,如下所示(完整代码请参考课件部分);

标签:QNetworkRequest,const,Qt,QByteArray,网络,C++,QNetworkReply,请求,网络接口
From: https://www.cnblogs.com/LyShark/p/18068071

相关文章

  • c++20 模板约束
    concept在c++20中,提案许久的concept被加入到标准中了,这也意味着不用再写恼人的SFINAE了(除非你是一个受虐狂,喜欢对着一堆报错中找到错误的位置)。c++20之前在c++20之前,如果需要对模板实参进行编译期检查,只能使用SFINAE,或者是部分使用c++17添加的ifconstexpr进行......
  • Qt--编译安装QWT
    1.下载https://sourceforge.net/projects/qwt/files/2.编译   编译参考如下:1QtCreator打开源码内的qwt.pro,注意:编译器选择Release版本,编译器使用与creator的一样的版本,这里使用msvc201532bit。2打开编译开关,在qwt->otherfiles->qwt.prf中,去掉QMAKE_RPATHDI......
  • Qt quint16 高低字节 quint8
    在C++中,将一个quint16(即无符号16位整数)拆分成高字节和低字节可以通过位运算来完成。quint16通常是通过Qt的数据类型quint16来表示的。以下是一个示例代码,演示如何将quint16拆分成高低字节:1#include<QtGlobal>2#include<iostream>34intmain(){5qu......
  • Qt/C++音视频开发69-保存监控pcm音频数据到mp4文件/监控录像/录像存储和回放/264/265/
    一、前言用ffmpeg做音视频保存到mp4文件,都会遇到一个问题,尤其是在视频监控行业,就是监控摄像头设置的音频是PCM/G711A/G711U,解码后对应的格式是pcm_s16be/pcm_alaw/pcm_mulaw,将这个原始的音频流保存到mp4文件是会报错的,在调用avformat_write_header写文件头的时候提示(-22)Invali......
  • c++从零实现reactor高并发服务器!!!
    环境准备linux虚拟机安装升级c/c++编译器gcc/g++选项源代码文件1源代码文件2...源代码文件n-o指定输出的文件名(不能和源文件同名默认是a.out)-g调试-On链接时优化减小体积(n=1-3)-c只编译用于生成库-std=c++11支持c++11标准安装man功能man级别接口......
  • 线段树(C++)
    线段树的本质就是树状数组,只不过线段树不再需要lowbit函数来定位对应数据的存储位置,取而代之的则是直接计算分叉结果位置。node结构体​ 通常而言,线段树所需要的存储空间约等于原数组的4倍。由于线段树需要存储区间的范围,所以我们需要自己定义一个新结构体来方便存储:constint......
  • (C++)树状数组和线段树的VSCode Snippet
    学都学了,肯定要往snippet里塞好东西嘛{ //Placeyoursnippetsforcpphere.Eachsnippetisdefinedunderasnippetnameandhasaprefix,bodyand //description.Theprefixiswhatisusedtotriggerthesnippetandthebodywillbeexpandedandinserted.......
  • 用c++实现净现值的计算
    我是用c++实现的,我是把贴现率保留了四位小数。下面是我写的代码:#include<iostream>#include<cmath>usingnamespacestd;floatjst(intj,floatm,floatlv){while(j!=0){m*=(1+lv);j--;}return1.0/m;}i......
  • Qt 将16进制的内容的QString字符串转为QByteArray数组
    1.QString存储十六进制内容我要发送的十六进制内容是0105040100将其储存在QString字符串中1QStringstr;2str="0105040100";2.核心语句将两位的字符串转换为16进制的Int型数字,然后通过强制类型转换成char类型的字符。(具体作用方式我还没去看,但是有用)(char)str.m......
  • Qt 常用数据类型转换
    1、int转QStringquint8转QString1quint8k=77;2QStringstr_1;3str_1=QString::number(k,10);4qDebug()<<str_1;//"77"5QStringstr_2=QString("%1").arg(k);6qDebug()<<str_2;//"77"2、quin......