[Qt first entered the rivers and lakes] Detailed description of the underlying architecture and principles of Qt QNetworkAccessManager

Yuxian: CSDN content partner, CSDN new star mentor, 51CTO (Top celebrity + expert blogger), github open source enthusiast (secondary development of go-zero source code, game back-end architecture https://github.com/Peakchen)

    

 

QNetworkAccessManager is a class in the Qt network module that manages network requests and responses. QNetworkAccessManager provides an easy way to send HTTP requests and handle responses. It is based on an event-driven architecture and can run in a background thread to avoid blocking the UI thread.

Underlying architecture:

The underlying architecture of QNetworkAccessManager is a Qt-based network module, which uses a multi-threaded architecture to process network requests and responses. QNetworkAccessManager contains several subcomponents, the most important of which are QNetworkReply and QNetworkRequest. QNetworkRequest is responsible for managing HTTP requests, while QNetworkReply is responsible for managing HTTP responses.

Realize the architecture diagram:

+----------------+              +-------------------+
|                |              |                   |
|  QNetworkReply |<-------------| QNetworkAccessManager |
|                |              |                   |
+----------------+              +-------------------+
         |                                    |
         |                                    |
         |                                    |
         |                                    |
         |                                    |
+--------v-----------------------------+  +---v-------------------------+
|                                        |  |                             |
|                  Network               |  |         Socket              |
|                                        |  |                             |
+----------------------------------------+  +-----------------------------+

QNetworkAccessManager is a network request manager object encapsulated by Qt, which contains multiple QNetworkReply objects for managing HTTP responses. Under the hood, QNetworkAccessManager uses the Socket objects in the Qt networking module to send and receive network requests and responses.

Principle detailed operation description:

Using QNetworkAccessManager in Qt is very simple. First, we need to create a QNetworkAccessManager object and use it to send HTTP requests. For example, the following code demonstrates how to use QNetworkAccessManager to send a simple HTTP GET request:

QNetworkAccessManager* manager = new QNetworkAccessManager(this);
QNetworkReply* reply = manager->get(QNetworkRequest(QUrl("http://www.example.com")));

In the above code, we first create a QNetworkAccessManager object and use the get() function to send an HTTP GET request. The get() function accepts a QNetworkRequest object as a parameter, which specifies the requested URL and other parameters. The get() function returns a QNetworkReply object, which is used to manage HTTP responses.

We can then use QNetworkReply's functions to access and manipulate the HTTP response. For example, the following code demonstrates how to read the content of an HTTP response:

QByteArray data = reply->readAll();

In the above code, we use the readAll() function to read the content of the HTTP response from the QNetworkReply object.

The principle of using functions in the class:

The most important functions in the QNetworkAccessManager class are get(), post(), put(), and deleteResource(), which are used to send HTTP GET, POST, PUT, and DELETE requests, respectively. finished() is a signal used to notify when an HTTP request is complete.

The following are the use cases and detailed introductions of some commonly used functions of the QNetworkAccessManager class in Qt using C++:

1. get()
This function is used to send HTTP GET request and get response. You can use to QNetworkRequestset the URL of the request, header information, etc.

#include <QNetworkAccessManager>
#include <QNetworkRequest>
#include <QNetworkReply>

// 创建QNetworkAccessManager对象
QNetworkAccessManager* manager = new QNetworkAccessManager();

// 创建QNetworkRequest对象并设置请求URL
QNetworkRequest request(QUrl("https://www.example.com"));

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

// 处理响应
connect(reply, &QNetworkReply::finished, [=]() {
    if (reply->error() == QNetworkReply::NoError) {
        QByteArray data = reply->readAll();
        // 处理响应数据
    } else {
        // 处理错误
    }
    
    // 清理资源
    reply->deleteLater();
});

2. post()
This function is used to send HTTP POST request and get response. You can use to QNetworkRequestset the request URL, header information, etc., and use QByteArrayto pass the request body data.

#include <QNetworkAccessManager>
#include <QNetworkRequest>
#include <QNetworkReply>

// 创建QNetworkAccessManager对象
QNetworkAccessManager* manager = new QNetworkAccessManager();

// 创建QNetworkRequest对象并设置请求URL
QNetworkRequest request(QUrl("https://www.example.com"));

// 设置请求头
request.setHeader(QNetworkRequest::ContentTypeHeader, "application/x-www-form-urlencoded");

// 创建请求体数据
QByteArray postData;
postData.append("key1=value1&key2=value2");

// 发送POST请求
QNetworkReply* reply = manager->post(request, postData);

// 处理响应
connect(reply, &QNetworkReply::finished, [=]() {
    if (reply->error() == QNetworkReply::NoError) {
        QByteArray data = reply->readAll();
        // 处理响应数据
    } else {
        // 处理错误
    }
    
    // 清理资源
    reply->deleteLater();
});

3. head()
This function is used to send HTTP HEAD request and get response header information. You can use to QNetworkRequestset the URL of the request, header information, etc.

#include <QNetworkAccessManager>
#include <QNetworkRequest>
#include <QNetworkReply>

// 创建QNetworkAccessManager对象
QNetworkAccessManager* manager = new QNetworkAccessManager();

// 创建QNetworkRequest对象并设置请求URL
QNetworkRequest request(QUrl("https://www.example.com"));

// 发送HEAD请求
QNetworkReply* reply = manager->head(request);

// 处理响应
connect(reply, &QNetworkReply::finished, [=]() {
    if (reply->error() == QNetworkReply::NoError) {
        QVariantMap headers = reply->rawHeaderPairs();
        // 处理响应头信息
    } else {
        // 处理错误
    }
    
    // 清理资源
    reply->deleteLater();
});

4. put()
This function is used to send HTTP PUT request and get response. You can use to QNetworkRequestset the request URL, header information, etc., and use QByteArrayto pass the request body data.

#include <QNetworkAccessManager>
#include <QNetworkRequest>
#include <QNetworkReply>

// 创建QNetworkAccessManager对象
QNetworkAccessManager* manager = new QNetworkAccessManager();

// 创建QNetworkRequest对象并设置请求URL
QNetworkRequest request(QUrl("https://www.example.com"));

// 设置请求头
request.setHeader(QNetworkRequest::ContentTypeHeader, "application/x-www-form-urlencoded");

// 创建请求体数据
QByteArray putData;
putData.append("key1=value1&key2=value2");

// 发送PUT请求
QNetworkReply* reply = manager->put(request, putData);

// 处理响应
connect(reply, &QNetworkReply::finished, [=]() {
    if (reply->error() == QNetworkReply::NoError) {
        QByteArray data = reply->readAll();
        // 处理响应数据
    } else {
        // 处理错误
    }
    
    // 清理资源
    reply->deleteLater();
});

These are use cases and introductions to some common functions of the QNetworkAccessManager class in Qt using C++.

Here is an example of a simple implementation:

#include <QtNetwork/QNetworkAccessManager>
#include <QtNetwork/QNetworkReply>
#include <QtNetwork/QNetworkRequest>

int main(int argc, char* argv[])
{
    QApplication app(argc, argv);

    QNetworkAccessManager* manager = new QNetworkAccessManager();
    QNetworkReply* reply = manager->get(QNetworkRequest(QUrl("http://www.example.com")));

    QObject::connect(reply, SIGNAL(finished()), &app, SLOT(quit()));

    app.exec();

    QByteArray data = reply->readAll();
    qDebug() << data;

    return 0;
}

In the above code, we first created a QNetworkAccessManager object and sent an HTTP GET request using the get() function. Then, we connected the finished() signal of the reply object to the application's quit() slot to exit the application when the HTTP request is complete. Finally, we use the readAll() function to read the content of the HTTP response from the QNetworkReply object.

An application example of using QNetworkAccessManager in the Web is to download files through the HTTP protocol. Here is an example of a simple implementation:

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>Download File</title>
</head>
<body>

    <form>
        <label for="url-input">URL:</label>
        <input id="url-input" type="text" name="url" value="https://www.example.com/file.pdf">
        <button id="download-button" type="button">Download</button>
    </form>

    <script>
        var button = document.getElementById("download-button");
        button.addEventListener("click", function() {
            var url = document.getElementById("url-input").value;
            var xhr = new XMLHttpRequest();
            xhr.open("GET", "/download?url=" + encodeURIComponent(url));
            xhr.responseType = "arraybuffer";
            xhr.onload = function() {
                if (this.status === 200) {
                    var blob = new Blob([this.response], {type: "application/pdf"});
                    var link = document.createElement("a");
                    link.href = URL.createObjectURL(blob);
                    link.download = "file.pdf";
                    link.click();
                } else {
                    alert("Download failed: " + this.statusText);
                }
            };
            xhr.send();
        });
    </script>

</body>
</html>

In the HTML code above, we have created a simple form with a URL input box and a download button. When the user clicks the download button, we send an HTTP GET request to the server using the XMLHttpRequest object, passing the URL as a query parameter. To download a PDF file, we set the content type of the response to "application/pdf" and convert the response to binary data.

On the server side, we can use Qt to handle HTTP requests and use QNetworkAccessManager to download files. Here is an example of a simple implementation:

#include <QCoreApplication>
#include <QtNetwork/QNetworkAccessManager>
#include <QtNetwork/QNetworkReply>
#include <QtNetwork/QNetworkRequest>
#include <QtCore/QUrlQuery>
#include <QtCore/QFile>
#include <QtCore/QDir>
#include <QtCore/QFileInfo>

void downloadFile(QNetworkAccessManager* manager, QUrl url, QString filename)
{
    QNetworkReply* reply = manager->get(QNetworkRequest(url));
    QObject::connect(reply, &QNetworkReply::finished, [reply, filename]() {
        if (reply->error() == QNetworkReply::NoError) {
            QFile file(QDir::temp().filePath(filename));
            if (file.open(QIODevice::WriteOnly)) {
                file.write(reply->readAll());
                file.close();
                qDebug() << "Downloaded file:" << file.fileName();
            } else {
                qWarning() << "Failed to write file:" << file.fileName() << "-" << file.errorString();
            }
        } else {
            qWarning() << "Download failed:" << reply->errorString();
        }
        reply->deleteLater();
    });
}

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

    QNetworkAccessManager manager;
    QObject::connect(&manager, &QNetworkAccessManager::finished, &app, &QCoreApplication::quit);

    QUrlQuery query;
    query.setQuery(app.arguments().value(1));
    QString url = query.queryItemValue("url");

    if (!url.isEmpty()) {
        downloadFile(&manager, QUrl(url), "file.pdf");
    } else {
        qDebug() << "Usage:" << app.applicationName() << "url=<url>";
    }

    app.exec();

    return 0;
}

In the above code, we first create a QNetworkAccessManager object and connect its finished() signal to the application's quit() slot function to exit the application after the download is complete. We then parse the URL query parameters using the QUrlQuery object and download the file using the QNetworkAccessManager object. After the download is complete, we save the file to a temporary directory and output the filename.

Guess you like

Origin blog.csdn.net/feng1790291543/article/details/131805121