C++ Qt開發:QNetworkAccessManager網路介面組件

来源:https://www.cnblogs.com/LyShark/p/18068071
-Advertisement-
Play Games

Qt 是一個跨平臺C++圖形界面開發庫,利用Qt可以快速開發跨平臺窗體應用程式,在Qt中我們可以通過拖拽的方式將不同組件放到指定的位置,實現圖形化開發極大的方便了開發效率,本章將重點介紹如何運用`QNetworkAccessManager`組件實現Web網頁訪問。QNetworkAccessMana... ...


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());
}

運行代碼,讀者可自行輸入特定的網站進行讀取測試,如下所示(完整代碼請參考課件部分);

文章出處:https://www.cnblogs.com/LyShark/p/18068071
本博客所有文章除特別聲明外,均採用 BY-NC-SA 許可協議。轉載請註明出處!
您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 8.1 C++內聯函數 提出的目的:為了提高程式運行速度。 內聯函數和普通函數的區別: 編譯方式: 內聯函數在編譯時會被直接替換到調用處,而不是像普通函數那樣通過函數調用的方式執行。這樣可以減少函數調用的開銷,提高程式執行效率。 普通函數則是通過函數調用的方式執行,會涉及函數棧的壓棧和出棧操作。 代 ...
  • Java Iterator Iterator 介面提供了一種迭代集合的方法,即順序訪問集合中的每個元素。它支持 hasNext() 和 next() 方法,用於檢查是否存在下一個元素以及獲取下一個元素。 獲取 Iterator 可以使用集合的 iterator() 方法獲取 Iterator 實例: ...
  • 摘要: 銀行卡歸屬地查詢介面是一種高效的方式,通過銀行卡號查詢銀行名稱、卡種、卡品牌以及發卡省份和城市等信息。本文將詳細介紹如何使用該介面,並附帶代碼說明。同時,也介紹了介面的特點和適用範圍,讓讀者能夠充分瞭解和運用該介面,方便快捷地獲取銀行卡發卡行所在地信息。 一、介面簡介 銀行卡歸屬地查詢介面是 ...
  • 1. 本篇文章目標 將下麵的excel中的寄存器表單讀入並構建一個字典 2. openpyxl的各種基本使用方法 2.1 打開工作簿 wb = openpyxl.load_workbook('test_workbook.xlsx') 2.2 獲取工作簿中工作表名字並得到工作表 ws = wb[wb. ...
  • 拓展閱讀 linux Shell 命令行-00-intro 入門介紹 linux Shell 命令行-02-var 變數 linux Shell 命令行-03-array 數組 linux Shell 命令行-04-operator 操作符 linux Shell 命令行-05-test 驗證是否符 ...
  • 在之前的多線程系列文章中,我們陸陸續續的介紹了Thread線程類相關的知識和用法,其實在Thread類上還有一層ThreadGroup類,也就是線程組。 ...
  • 2024年3月4日,官方宣佈推出 Claude 3 模型系列,它在廣泛的認知任務中樹立了新的行業基準。該系列包括三個按能力遞增排序的最先進模型:Claude 3 Haiku、Claude 3 Sonnet 和 Claude 3 Opus。每個後續模型都提供越來越強大的性能,允許用戶為其特定應用選擇智 ...
  • 大家好,我是你們的老伙計秀才!今天帶來的是[深入淺出Java多線程]系列的第十一篇內容:AQS(*AbstractQueuedSynchronizer*)。大家覺得有用請點贊,喜歡請關註!秀才在此謝過大家了!!! ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...