【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后为:"<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组为:"<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 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 

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 

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()<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() << "接收到的数据" <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 
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

你可能感兴趣的:(Qt,qt,http)