【QT】 给http服务器发送GET/POST请求并接收返回值

目录

一、注意事项和重要代码

1、使用场景

2、发送请求的方式有两种

3、使用前提

4、get主要代码

5、post第一种主要代码

6、post第二种主要代码

二、详细代码

三、结果图


一、注意事项和重要代码

1、使用场景

qt,需要对服务器发送请求(包含报文),并接收服务器的返回值;服务器用的是mongoose模拟的服务器;

2、发送请求的方式有两种

GET和POST,两种方式的不同:Get将参数直接与网址整合为一个整体,而Post则将其拆为两个部分,一部分是网址,另一个部分才是参数,并且必须为其设置报文setHeader,否则服务器是无法找到参数的

本文主要介绍三种发送不同请求:

1)一种是GET方式请求,此时没有发送的报文,但是会有服务器返回值;

2)其余两种是POST请求,都有发送的报文,其中第一种发送的报文是一组json格式的数据(有返回信息);第二种是利用事件循环的方式发送一组json格式数据报文,因为在项目中都是有线程的,如果不利用事件循环进行阻塞,会导致请求无法发出。

三种具体方式见主要代码,最下方的详细代码实现的是get请求,如果想更改其他两种方式,更换startRequest函数即可,但是在使用post事件循环方式时,需要将.h中的startRequest定义更改为

    void startRequest(const QString &hostName,
                                 const QString &diskName,
                                 const QString &diskSize,
                                 const QString &mount,
                                 const QString &format,
                                 const QString &authStatus,
                                 const QString &keyfile);

在构造函数中调用时,改为

startRequest("2.3.4.5","dev/sda123","10G","/mnt","ext4","1","this is .key's content");

3、使用前提

一定要注意!!!!!,不然无法与服务器连接

在.pro文件中添加

QT += network

4、get主要代码

void MainWindow::startRequest(const QUrl &requestedUrl){
    url = requestedUrl;
    manager = new QNetworkAccessManager(this);
    req.setUrl(url);
    //由于请求发生重定向,所以要加上这行代码,设置自动跳转,否则会返回 302
    req.setAttribute(QNetworkRequest::FollowRedirectsAttribute, true);
    reply = manager->get(req);
    connect(reply,&QNetworkReply::finished,this,&MainWindow::replyFinished);

}

5、post第一种主要代码

void MainWindow::startRequest(const QUrl &requestedUrl){
    url = requestedUrl;
    //post
    QByteArray array;
    json.insert("table_operation","select");
    QJsonDocument document;
    document.setObject(json);
    array = document.toJson(QJsonDocument::Compact);
    qDebug()<<"array在转为json后为:"<<array;

    manager = new QNetworkAccessManager(this);
    req.setUrl(url);
    req.setHeader(QNetworkRequest::ContentTypeHeader,QVariant("application/json"));
    req.setAttribute(QNetworkRequest::FollowRedirectsAttribute, true);
    reply = manager->post(req,array);
    connect(reply,&QNetworkReply::finished,this,&MainWindow::replyFinished);
}

6、post第二种主要代码

void MainWindow::sendRequest(const QString &hostName,
                             const QString &diskName,
                             const QString &diskSize,
                             const QString &mount,
                             const QString &format,
                             const QString &authStatus,
                             const QString &keyfile)
{
    //1.json格式传输报文
    QJsonObject json;
    QJsonDocument jsonDoc;

    //打包json数据
    json["host_name"] = hostName;
    json["disk_name"] = diskName;
    json["disk_size"] = diskSize;
    json["mount"] = mount;
    json["format"] = format;
    json["certification_status"] = authStatus;
    json["keyfile_path"] = keyfile;

    jsonDoc.setObject(json);
    QByteArray dataArray = jsonDoc.toJson(QJsonDocument::Compact);
    qDebug()<< "jsondata组为:"<<dataArray;

    //2.构造URL&&请求头
    QString urlStr = "http://127.0.0.1:8000/test";
    qDebug()<<"url地址为:"<<urlStr;
    url = urlStr;
    //构造请求头
    req.setUrl(url);
    req.setHeader(QNetworkRequest::ContentTypeHeader,QVariant("application/json;charset=UTF-8"));
//    req.setRawHeader("Connection", "Keep-Alive");

    //3.post数据
    manager = new QNetworkAccessManager(this);
    reply = manager->post(req,dataArray);
    QEventLoop eventLoop;
    connect(manager,SIGNAL(finished(QNetworkReply*)),&eventLoop,SLOT(quit()));
    connect(reply,&QNetworkReply::finished,this,&MainWindow::replyFinished);
    eventLoop.exec();
}

二、详细代码

QT创建一个继承QWidget的Qt Widgets Application就行

1、mainwindow.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QDebug>
#include <QtNetwork>
#include <QNetworkAccessManager>
#include <QNetworkReply>
#include <QNetworkRequest>
#include <QTextCodec>
#include <QFile>
#include <QTextStream>
#include <QDateTime>

QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    MainWindow(QWidget *parent = nullptr);
    ~MainWindow();
    void startRequest(const QUrl &requestedUrl);

private:
    Ui::MainWindow *ui;

private:
    // [3] 添加对象
    QUrl url;
    QNetworkRequest req;
    QNetworkReply *reply;
    QNetworkAccessManager *manager;

private slots:
//    void startRequest(const QUrl &requestedUrl);
    void replyFinished();

};
#endif // MAINWINDOW_H

2、mainwindow.cpp

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QLabel>

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    //调用函数发送请求,参数是请求的服务器地址
    startRequest( QUrl("http://127.0.0.1:8000/test"));

}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::startRequest(const QUrl &requestedUrl){
    url = requestedUrl;
    manager = new QNetworkAccessManager(this);
    req.setUrl(url);
    //由于请求发生重定向,所以一定要加上这行代码,设置自动跳转,否则会返回 302
    req.setAttribute(QNetworkRequest::FollowRedirectsAttribute, true);
//    req.setRawHeader("Accept","text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9");
//    req.setRawHeader("User-Agent","Mozilla/5.0 (Windows NT 10.0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.198 Safari/537.36");
    //get方式发送请求
    reply = manager->get(req);
    //将服务器的返回信号与replyFinished槽连接起来,当服务器返回消息时,会在槽里做相应操作
    connect(reply,&QNetworkReply::finished,this,&MainWindow::replyFinished);

}

void MainWindow::replyFinished(){

    // <1>判断有没有错误
    if (reply->error()){
        qDebug()<<reply->errorString();
        reply->deleteLater();
        return;
    }

    // <2>检测网页返回状态码,常见是200,404等,200为成功
    int statusCode  = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
    qDebug() << "statusCode:" << statusCode;

    // <3>判断是否需要重定向
    if (statusCode >= 200 && statusCode <300){
        // ok

        // 准备读数据
        QTextCodec *codec = QTextCodec::codecForName("utf8");
        QString all = codec->toUnicode(reply->readAll());
        qDebug() << "接收到的数据" <<all;

        //显示在mainwindow 测试,将服务器返回值打印至label上,服务器用的是mongoose模拟
        QLabel *label = new QLabel(this);
        label->setText(all);
        label->move(200,200);
        label->setVisible(true);

        // 数据读取完成之后,清除reply
        reply->deleteLater();
        reply = nullptr;

    } else if (statusCode >=300 && statusCode <400){
        // redirect

        // 获取重定向信息
        const QVariant redirectionTarget = reply->attribute(QNetworkRequest::RedirectionTargetAttribute);
        // 检测是否需要重定向,如果不需要则读数据
        if (!redirectionTarget.isNull()) {
            const QUrl redirectedUrl = url.resolved(redirectionTarget.toUrl());

            reply->deleteLater();
            reply = nullptr;

            startRequest(redirectedUrl);
            qDebug()<< "http redirect to " << redirectedUrl.toString();
            return;
        }
    }
}

3、main.cpp

#include "mainwindow.h"
#include <QApplication>
int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    MainWindow w;
    w.show();
    return a.exec();
}

这个项目的代码是get请求方式,如果要换成post,只需要将startRequest函数换成博客开头提到的【post主要代码】即可;

replyFinished函数是接收服务器返回的状态值和返回值的,可以自己做需要的操作。

三、结果图

1、服务器接收到的POST请求信息:

2、GET请求没有发送报文,但是能收到mongoose模拟服务器的返回值:

四、参考

Qt实现HTTP的Get/Post请求_china_jeffery的博客-CSDN博客_qt http

QT中使用QEventLoop来实现事件循环_「已注销」的博客-CSDN博客_qeventloop

https://www.cnblogs.com/cjdty/p/10659685.html

##END

阅读终点,创作起航,您可以撰写心得或摘录文章要点写篇博文。去创作
  • 13
    点赞
  • 55
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论
### 回答1: Qt可以通过QNetworkAccessManager类来实现HTTPGET/POST请求。 1. GET请求: ```cpp QNetworkAccessManager *manager = new QNetworkAccessManager(this); QNetworkRequest request; request.setUrl(QUrl("http://www.example.com")); QNetworkReply *reply = manager->get(request); connect(reply, &QNetworkReply::finished, [=]() { if (reply->error() == QNetworkReply::NoError) { QByteArray data = reply->readAll(); // 处理返回的数据 } else { // 处理错误 } reply->deleteLater(); }); ``` 2. POST请求: ```cpp QNetworkAccessManager *manager = new QNetworkAccessManager(this); QNetworkRequest request; request.setUrl(QUrl("http://www.example.com")); request.setHeader(QNetworkRequest::ContentTypeHeader, "application/x-www-form-urlencoded"); QByteArray postData; postData.append("key1=value1&key2=value2"); QNetworkReply *reply = manager->post(request, postData); connect(reply, &QNetworkReply::finished, [=]() { if (reply->error() == QNetworkReply::NoError) { QByteArray data = reply->readAll(); // 处理返回的数据 } else { // 处理错误 } reply->deleteLater(); }); ``` 以上代码仅供参考,具体实现还需要根据实际情况进行调整。 ### 回答2: Qt是一个跨平台的GUI应用程序开发框架,也支持网络编程。Qt通过QNetworkAccessManager类来访问网络资源,可以很容易地实现HTTPGETPOST请求GET请求: 使用Qt进行GET请求时,需要创建QNetworkRequest对象并设置URL,然后传递到QNetworkAccessManager的get函数中。QNetworkAccessManager会自动地发送请求,并在请求完成时发出finished信号。 示例代码如下: ``` QNetworkRequest request; request.setUrl(QUrl("http://www.example.com")); QNetworkReply *reply = manager->get(request); connect(reply, &QNetworkReply::finished, [=]() { if (reply->error() == QNetworkReply::NoError) { QByteArray data = reply->readAll(); qDebug() << data; } else { qDebug() << reply->errorString(); } reply->deleteLater(); }); ``` POST请求: 使用Qt进行POST请求时,需要创建QNetworkRequest对象并设置URL,然后传递到QNetworkAccessManager的post函数中,同时传递POST数据。Qt支持多种数据格式,包括字符串、字节数组和QIODevice对象。在POST请求中,需要设置Content-Type头部以指定POST数据的格式。 示例代码如下: ``` QNetworkRequest request; request.setUrl(QUrl("http://www.example.com")); request.setHeader(QNetworkRequest::ContentTypeHeader, "application/x-www-form-urlencoded"); QByteArray postData; postData.append("param1=value1&param2=value2"); QNetworkReply *reply = manager->post(request, postData); connect(reply, &QNetworkReply::finished, [=]() { if (reply->error() == QNetworkReply::NoError) { QByteArray data = reply->readAll(); qDebug() << data; } else { qDebug() << reply->errorString(); } reply->deleteLater(); }); ``` 以上是Qt实现HTTPGETPOST请求的基本方案,根据实际需求可以自行调整和添加参数。 ### 回答3: Qt是一种跨平台应用程序开发框架,它提供了许多方便的类和函数,方便程序员开发功能强大的应用程序。Qt提供了QNetworkAccessManager类,可以用来实现Http请求GETPOST方法。 QNetworkAccessManager是Qt中提供的用于管理网络请求的类,它使我们可以进行HTTP请求,下载和上传文件等操作。在使用QNetworkAccessManager时,首先要创建一个实例对象,并为该对象关联一个信号槽。当网络请求完成时,QNetworkAccessManager会发出一个信号,告知程序请求已完成。 下面是一个简单的例子,展示了如何使用QNetworkAccessManager实现HttpGET请求: ``` QNetworkAccessManager *manager = new QNetworkAccessManager(this); QUrl url("http://www.example.com"); QNetworkRequest request(url); QNetworkReply *reply = manager->get(request); connect(reply, SIGNAL(finished()), this, SLOT(replyFinished())); void MyClass::replyFinished() { qDebug() << reply->readAll(); reply->deleteLater(); } ``` 在上面的代码中,我们首先创建了QNetworkAccessManager的一个实例对象,然后为其关联了一个URL,发起了一个GET请求。当请求完成后,replyFinished()函数会被调用,我们在该函数中使用readAll()函数读取服务器返回的数据,并将其打印到应用程序的控制台上。 如果我们需要实现POST请求,则只需要将上面的代码稍作修改即可: ``` QNetworkAccessManager *manager = new QNetworkAccessManager(this); QUrl url("http://www.example.com"); QNetworkRequest request(url); request.setHeader(QNetworkRequest::ContentTypeHeader, "application/x-www-form-urlencoded"); QByteArray postData; postData.append("key1=value1"); postData.append("&key2=value2"); QNetworkReply *reply = manager->post(request, postData); connect(reply, SIGNAL(finished()), this, SLOT(replyFinished())); void MyClass::replyFinished() { qDebug() << reply->readAll(); reply->deleteLater(); } ``` 在上述代码中,我们创建了一个QByteArray对象,用来存放需要提交的POST数据。然后用QNetworkAccessManager的post()函数提交POST请求,并在请求完成后读取服务器的响应数据。其中setHeader()函数用来设置POST请求的Content-Type header,告诉服务器发送的数据的格式。 总之,Qt提供的QNetworkAccessManager类可以方便实现HTTPGETPOST请求。开发者可以根据自己的需求进行调整,并根据服务器返回的数据进行相应的处理和逻辑控制。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Wyn_

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值