Qt实现HTTP的Get/Post请求及示例

借助Qt的NetWork模块,可以轻松的实现HTTP的Get/Post请求,而不需要再次引用像libcurl这样的第三方库。

当然,Qt的NetWork模块提供的功能远远不只是HTTP方面的。

头文件

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

另外,使用Qt网络模块还需要引用Qt5Network.lib库。
Get
先构造一个QNetworkAccessManager对象,QNetworkAccessManager对象提供了发送QNetworkRequest网络请求和接收QNetworkReply网络回复的功能。

QNetworkAccessManager还提供了缓存和Cookie管理、代理设置等功能。详见:https://doc.qt.io/qt-5/qnetworkaccessmanager.html

QNetworkRequest提供了对本次网络请求的封装,在本示例中只是构造了一个最简单的requset,没有进行任何参数设置。
QNetworkRequest提供了很多方法来对请求进行配置,比如我们可以使用QNetworkRequest::setHeader设置请求头等。

void QtGuiApplication::onBtnGetClicked() {
	QNetworkRequest request;
	QNetworkAccessManager* naManager = new QNetworkAccessManager(this);
	QMetaObject::Connection connRet = QObject::connect(naManager, SIGNAL(finished(QNetworkReply*)), this, SLOT(requestFinished(QNetworkReply*)));
	Q_ASSERT(connRet);

	request.setUrl(QUrl("https://www.baidu.com"));
	QNetworkReply* reply = naManager->get(request);
}

请求是异步的,当请求完成之后,会调用void requestFinished(QNetworkReply* reply);
槽函数:

void QtGuiApplication::requestFinished(QNetworkReply* reply) {
	// 获取http状态码
	QVariant statusCode = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute);
	if(statusCode.isValid())
		qDebug() << "status code=" << statusCode.toInt();

	QVariant reason = reply->attribute(QNetworkRequest::HttpReasonPhraseAttribute).toString();
	if(reason.isValid())
		qDebug() << "reason=" << reason.toString();

	QNetworkReply::NetworkError err = reply->error();
	if(err != QNetworkReply::NoError) {
		qDebug() << "Failed: " << reply->errorString();
	}
	else {
		// 获取返回内容
		qDebug() << reply->readAll();
	}
}

Post

void QtGuiApplication::onBtnPushClicked() {
	QNetworkRequest request;
	QNetworkAccessManager* naManager = new QNetworkAccessManager(this);
	QMetaObject::Connection connRet = QObject::connect(naManager, SIGNAL(finished(QNetworkReply*)), this, SLOT(requestFinished(QNetworkReply*)));
	Q_ASSERT(connRet);

	request.setUrl(QUrl("https://www.baidu.com"));
	
	QString testData = "test";
	QNetworkReply* reply = naManager->post(request, testData.toUtf8());
}

同样,请求也是异步的,当请求完成之后,会调用void requestFinished(QNetworkReply* reply);
槽函数(和Get一样):

void QtGuiApplication::requestFinished(QNetworkReply* reply) {
	// 获取http状态码
	QVariant statusCode = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute);
	if(statusCode.isValid())
		qDebug() << "status code=" << statusCode.toInt();

	QVariant reason = reply->attribute(QNetworkRequest::HttpReasonPhraseAttribute).toString();
	if(reason.isValid())
		qDebug() << "reason=" << reason.toString();

	QNetworkReply::NetworkError err = reply->error();
	if(err != QNetworkReply::NoError) {
		qDebug() << "Failed: " << reply->errorString();
	}
	else {
		// 获取返回内容
		qDebug() << reply->readAll();
	}
}

具体实例:
异步通信实例:
当涉及到Qt与HTTP通信时,可以使用Qt的QNetworkAccessManager类进行POST和GET请求的发送。下面是一个封装了POST和GET请求的示例,同时支持传入JSON格式参数:

#include <QNetworkAccessManager>
#include <QNetworkReply>
#include <QNetworkRequest>
#include <QJsonObject>
#include <QJsonDocument>
#include <QVariantMap>

class HttpHelper : public QObject
{
    Q_OBJECT

public:
    HttpHelper(QObject* parent = nullptr)
        : QObject(parent)
    {
        networkManager = new QNetworkAccessManager(this);
        connect(networkManager, &QNetworkAccessManager::finished, this, &HttpHelper::onReplyReceived);
    }

    void sendPostRequest(const QString& url, const QVariantMap& parameters)
    {
        QJsonDocument jsonDoc = QJsonDocument::fromVariant(QVariant(parameters));
        QByteArray postData = jsonDoc.toJson();

        QNetworkRequest request(url);
        request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");

        networkManager->post(request, postData);
    }

    void sendGetRequest(const QString& url, const QVariantMap& parameters)
    {
        QUrl requestUrl(url);

        QUrlQuery urlQuery;
        for (const QString& key : parameters.keys()) {
            urlQuery.addQueryItem(key, parameters.value(key).toString());
        }
        requestUrl.setQuery(urlQuery);

        QNetworkRequest request(requestUrl);
        networkManager->get(request);
    }

signals:
    void replyReceived(const QByteArray& responseData);

private slots:
    void onReplyReceived(QNetworkReply* reply)
    {
        if (reply->error() == QNetworkReply::NoError) {
            QByteArray responseData = reply->readAll();
            emit replyReceived(responseData);
        } else {
            // Handle error case
        }

        reply->deleteLater();
    }

private:
    QNetworkAccessManager* networkManager;
};

在上述示例中,HttpHelper类封装了QNetworkAccessManager来发送POST和GET请求。sendPostRequest和sendGetRequest方法分别用于发送POST和GET请求,并接受一个QVariantMap类型的参数,该参数将作为JSON格式的数据发送到服务器。

通过QJsonDocument,将QVariantMap转换为JSON格式的QByteArray,并将其作为POST请求的数据发送。

对于GET请求,使用QUrlQuery将参数添加到URL中。

在收到HTTP响应后,通过QNetworkAccessManager的finished信号和onReplyReceived槽函数进行处理。如果没有错误发生,则读取响应数据并通过replyReceived信号进行传递。

使用示例:

HttpHelper httpHelper;

// 发送POST请求
QVariantMap postData;
postData["name"] = "John Doe";
postData["age"] = 30;

httpHelper.sendPostRequest("https://example.com/api", postData);

// 发送GET请求
QVariantMap getParams;
getParams["param1"] = "value1";
getParams["param2"] = "value2";

httpHelper.sendGetRequest("https://example.com/api", getParams);

可以连接HttpHelper的replyReceived信号,以接收HTTP响应数据。

connect(&httpHelper, &HttpHelper::replyReceived, this, &MyClass::handleResponse);

void MyClass::handleResponse(const QByteArray& responseData)
{
    // 处理响应数据
}

在上述示例中,封装的HTTP请求方法是异步的。
QNetworkAccessManager使用异步方式发送请求,并通过信号和槽机制来处理响应。

当请求完成时,会发出finished信号,然后调用onReplyReceived槽函数来处理响应数据。

这种异步方式允许应用程序在等待响应时继续执行其他任务,而不会被阻塞。一旦响应可用,会触发相应的信号,以便应用程序能够及时处理响应数据。

在使用封装的HttpHelper类时,你可以连接其replyReceived信号,并在槽函数中处理响应数据。这样可以确保在收到响应后及时进行处理。

如果你需要实现同步的消息传递,可以使用Qt的事件循环机制来等待并处理HTTP请求的响应。下面是一个示例:

#include <QNetworkAccessManager>
#include <QNetworkReply>
#include <QNetworkRequest>
#include <QJsonObject>
#include <QJsonDocument>
#include <QVariantMap>
#include <QEventLoop>

class HttpHelper : public QObject
{
    Q_OBJECT

public:
    HttpHelper(QObject* parent = nullptr)
        : QObject(parent)
    {
        networkManager = new QNetworkAccessManager(this);
    }

    QByteArray sendPostRequest(const QString& url, const QVariantMap& parameters)
    {
        QJsonDocument jsonDoc = QJsonDocument::fromVariant(QVariant(parameters));
        QByteArray postData = jsonDoc.toJson();

        QNetworkRequest request(url);
        request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");

        QNetworkReply* reply = networkManager->post(request, postData);
        QEventLoop eventLoop;
        connect(reply, &QNetworkReply::finished, &eventLoop, &QEventLoop::quit);
        eventLoop.exec();

        QByteArray responseData;
        if (reply->error() == QNetworkReply::NoError) {
            responseData = reply->readAll();
        }

        reply->deleteLater();
        return responseData;
    }

    QByteArray sendGetRequest(const QString& url, const QVariantMap& parameters)
    {
        QUrl requestUrl(url);

        QUrlQuery urlQuery;
        for (const QString& key : parameters.keys()) {
            urlQuery.addQueryItem(key, parameters.value(key).toString());
        }
        requestUrl.setQuery(urlQuery);

        QNetworkRequest request(requestUrl);

        QNetworkReply* reply = networkManager->get(request);
        QEventLoop eventLoop;
        connect(reply, &QNetworkReply::finished, &eventLoop, &QEventLoop::quit);
        eventLoop.exec();

        QByteArray responseData;
        if (reply->error() == QNetworkReply::NoError) {
            responseData = reply->readAll();
        }

        reply->deleteLater();
        return responseData;
    }

private:
    QNetworkAccessManager* networkManager;
};

在这个示例中,HttpHelper类中的sendPostRequest和sendGetRequest方法是同步的,它们会在等待响应期间阻塞事件循环,直到收到响应为止。

通过创建QEventLoop对象并连接QNetworkReply的finished信号,我们可以在调用exec()方法后等待响应。

一旦收到响应,事件循环退出,继续执行后续代码。然后我们读取响应数据并返回。

使用示例:

HttpHelper httpHelper;

// 发送同步POST请求
QVariantMap postData;
postData["name"] = "John Doe";
postData["age"] = 30;

QByteArray postResponse = httpHelper.sendPostRequest("https://example.com/api", postData);
// 处理postResponse

// 发送同步GET请求
QVariantMap getParams;
getParams["param1"] = "value1";
getParams["param2"] = "value2";

QByteArray getResponse = httpHelper.sendGetRequest("https://example.com/api", getParams);
// 处理getResponse

需要注意的是,使用同步方式发送HTTP请求会导致阻塞事件循环,这可能会对应用程序的响应性产生负面影响。因此,在考虑使用同步方式时,请仔细评估你的应用程序需求和性能要求。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,下面是一个简单的示例代码,可以实现GETPOST请求并返回JSON数据: ```C++ #include <QCoreApplication> #include <QNetworkAccessManager> #include <QNetworkRequest> #include <QNetworkReply> #include <QJsonDocument> #include <QJsonObject> class NetworkManager : public QObject { Q_OBJECT public: explicit NetworkManager(QObject *parent = nullptr) : QObject(parent) { manager = new QNetworkAccessManager(this); connect(manager, &QNetworkAccessManager::finished, this, &NetworkManager::onReplyFinished); } void sendRequest(const QString &url, const QString &method = "GET", const QJsonObject &data = QJsonObject()) { QNetworkRequest request; request.setUrl(QUrl(url)); request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json"); if (method == "GET") { manager->get(request); } else { QJsonDocument jsonDoc(data); QByteArray jsonData = jsonDoc.toJson(); manager->post(request, jsonData); } } signals: void requestFinished(const QJsonObject &result); private slots: void onReplyFinished(QNetworkReply *reply) { if (reply->error() == QNetworkReply::NoError) { QByteArray data = reply->readAll(); QJsonDocument jsonDoc = QJsonDocument::fromJson(data); QJsonObject result = jsonDoc.object(); emit requestFinished(result); } else { qDebug() << "Network error: " << reply->errorString(); } reply->deleteLater(); } private: QNetworkAccessManager *manager; }; int main(int argc, char *argv[]) { QCoreApplication a(argc, argv); NetworkManager networkManager; QObject::connect(&networkManager, &NetworkManager::requestFinished, [](const QJsonObject &result) { qDebug() << "Result: " << result; }); // 发送GET请求 networkManager.sendRequest("https://jsonplaceholder.typicode.com/todos/1"); // 发送POST请求 QJsonObject postData; postData.insert("key", "value"); networkManager.sendRequest("http://example.com/api", "POST", postData); return a.exec(); } #include "main.moc" ``` 在上面的示例中,我们创建了一个名为NetworkManager的类,用于发送网络请求,并在请求完成时发出信号。在main函数中,我们创建了一个NetworkManager对象,并连接requestFinished信号,以便在请求完成后输出返回的JSON数据。 使用sendRequest函数发送GETPOST请求。如果发送GET请求,则只需要传递URL和请求方法(默认为"GET");如果发送POST请求,则还需要传递JSON数据。 在请求完成时,会调用onReplyFinished槽函数,该函数将返回的JSON数据解析为QJsonObject,并发出requestFinished信号,以便在主函数中处理返回的数据。 注意,在使用QNetworkAccessManager发送网络请求时,需要在请求完成后调用deleteLater函数,以避免内存泄漏。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值