Qt 是一個跨平臺C++圖形界面開發庫,利用Qt可以快速開發跨平臺窗體應用程式,在Qt中我們可以通過拖拽的方式將不同組件放到指定的位置,實現圖形化開發極大的方便了開發效率,本章將重點介紹如何運用`QNetworkAccessManager`組件實現Web網頁訪問。QNetworkAccessMana... ...
Qt 是一個跨平臺C++圖形界面開發庫,利用Qt可以快速開發跨平臺窗體應用程式,在Qt中我們可以通過拖拽的方式將不同組件放到指定的位置,實現圖形化開發極大的方便了開發效率,本章將重點介紹如何運用QNetworkAccessManager
組件實現Web網頁訪問。
QNetworkAccessManager是Qt網路模塊中的關鍵類,用於管理網路訪問和請求。作為一個網路請求的調度中心,它為Qt應用程式提供了發送和接收各種類型的網路請求的能力,包括常見的GET、POST、PUT、DELETE等。這個模塊的核心功能在於通過處理QNetworkReply
和QNetworkRequest
來實現與網路資源的交互。
通過QNetworkAccessManager
,Qt應用程式能夠輕鬆地與遠程伺服器通信,獲取數據或將數據上傳到伺服器。這種網路請求的管理不僅是非同步的,以確保不會阻塞主線程,還提供了豐富的信號和槽機制,使得開發者可以靈活地處理不同階段的網路操作。
通常,QNetworkAccessManager
會與QNetworkReply
和QNetworkRequest
一起使用。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
網路模塊,併在頭文件中引入QNetworkAccessManager
、QNetworkReply
、QNetworkRequest
三個類,在建立訪問時首先使用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錯誤的列表。 |
這些信號提供了豐富的信息,使開發者能夠在不同階段處理網路請求。同理,在下載和上傳過程中可以使用downloadProgress
和uploadProgress
信號來獲取進度信息,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 許可協議。轉載請註明出處!