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

简介: QT 给http服务器发送GET/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请求信息:


1.png1.png


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


1.png


四、参考


https://blog.csdn.net/china_jeffery/article/details/83246355


https://blog.csdn.net/qiufenpeng/article/details/81583768


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


END


相关文章
|
1天前
|
前端开发 JavaScript Java
如何捕获和处理HTTP GET请求的异常
如何捕获和处理HTTP GET请求的异常
|
20天前
|
JSON JavaScript 前端开发
《进阶篇第6章:vue中的ajax》包括回顾发送ajax请求方式、vue-cli脚手架配置代理服务器、vue-resource
《进阶篇第6章:vue中的ajax》包括回顾发送ajax请求方式、vue-cli脚手架配置代理服务器、vue-resource
55 22
|
5天前
|
存储 缓存 网络协议
计算机网络常见面试题(二):浏览器中输入URL返回页面过程、HTTP协议特点,GET、POST的区别,Cookie与Session
计算机网络常见面试题(二):浏览器中输入URL返回页面过程、HTTP协议特点、状态码、报文格式,GET、POST的区别,DNS的解析过程、数字证书、Cookie与Session,对称加密和非对称加密
|
5天前
|
缓存 安全 API
http 的 get 和 post 区别 1000字
【10月更文挑战第27天】GET和POST方法各有特点,在实际应用中需要根据具体的业务需求和场景选择合适的请求方法,以确保数据的安全传输和正确处理。
|
20天前
|
前端开发 JavaScript Java
第6章:Vue中的ajax(包含:回顾发送ajax请求方式、vue-cli脚手架配置代理服务器)
第6章:Vue中的ajax(包含:回顾发送ajax请求方式、vue-cli脚手架配置代理服务器)
47 4
|
22天前
|
网络协议 Ubuntu Linux
gpg从公钥服务器接收失败(gpg: keyserver receive failed: Server indicated a failure)
通过上述步骤,大多数情况下应该能够解决GPG从公钥服务器接收失败的问题。如果问题依旧存在,可能需要进一步调查与公钥服务器相关的更深层次的技术问题,或者考虑在相关社区论坛寻求帮助。
100 1
|
1月前
|
JSON 编解码 安全
【HTTP】方法(method)以及 GET 和 POST 的区别
【HTTP】方法(method)以及 GET 和 POST 的区别
82 1
|
5天前
|
弹性计算
阿里云2核16G服务器多少钱一年?亲测价格查询1个月和1小时收费标准
阿里云2核16G服务器提供多种ECS实例规格,内存型r8i实例1年6折优惠价为1901元,按月收费334.19元,按小时收费0.696221元。更多规格及详细报价请访问阿里云ECS页面。
37 9
|
1天前
|
监控 Ubuntu Linux
使用VSCode通过SSH远程登录阿里云Linux服务器异常崩溃
通过 VSCode 的 Remote - SSH 插件远程连接阿里云 Ubuntu 22 服务器时,会因高 CPU 使用率导致连接断开。经排查发现,VSCode 连接根目录 ".." 时会频繁调用"rg"(ripgrep)进行文件搜索,导致 CPU 负载过高。解决方法是将连接目录改为"root"(或其他具体的路径),避免不必要的文件检索,从而恢复正常连接。
|
5天前
|
弹性计算 异构计算
2024年阿里云GPU服务器多少钱1小时?亲测价格查询方法
2024年阿里云GPU服务器每小时收费因实例规格不同而异。可通过阿里云GPU服务器页面选择“按量付费”查看具体价格。例如,NVIDIA A100的gn7e实例为34.742元/小时,NVIDIA A10的gn7i实例为12.710156元/小时。更多详情请访问阿里云官网。
34 2