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


相关文章
|
13天前
|
JSON Java 数据格式
java操作http请求针对不同提交方式(application/json和application/x-www-form-urlencoded)
java操作http请求针对不同提交方式(application/json和application/x-www-form-urlencoded)
66 25
java操作http请求针对不同提交方式(application/json和application/x-www-form-urlencoded)
|
12天前
|
Web App开发 大数据 应用服务中间件
什么是 HTTP Range请求(范围请求)
HTTP Range 请求是一种非常有用的 HTTP 功能,允许客户端请求资源的特定部分,从而提高传输效率和用户体验。通过合理使用 Range 请求,可以实现断点续传、视频流播放和按需加载等功能。了解并掌握 HTTP Range 请求的工作原理和应用场景,对开发高效的网络应用至关重要。
51 15
|
16天前
|
数据采集 JSON 测试技术
Grequests,非常 Nice 的 Python 异步 HTTP 请求神器
在Python开发中,处理HTTP请求至关重要。`grequests`库基于`requests`,支持异步请求,通过`gevent`实现并发,提高性能。本文介绍了`grequests`的安装、基本与高级功能,如GET/POST请求、并发控制等,并探讨其在实际项目中的应用。
25 3
|
13天前
|
Web App开发 网络安全 数据安全/隐私保护
Lua中实现HTTP请求的User-Agent自定义
Lua中实现HTTP请求的User-Agent自定义
|
Web App开发 前端开发 Java
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html><head><meta http-equiv="Cont
线程的状态有:new、runnable、running、waiting、timed_waiting、blocked、dead 当执行new Thread(Runnabler)后,新创建出来的线程处于new状态,这种线程不可能执行 当执行thread.start()后,线程处于runnable状态,这种情况下只要得到CPU,就可以开始执行了。
736 0
|
Web App开发 前端开发 Java
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html><head><meta http-equiv="Cont
ZooKeeper 保证了数据的强一致性,  zk集群中任意节点(一个zkServer)上的相同znode下的数据一定是相同的。
806 0
|
Web App开发 数据库
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html><head><meta http-equiv="Cont
可伸缩系统的架构经验 Feb 27th, 2013 | Comments 最近,阅读了Will Larson的文章Introduction to Architecting System for Scale,感觉很有价值。
2213 0
|
Web App开发 前端开发 Java
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html><head><meta http-equiv="Cont
 Connection reset by peer的常见原因: 1)服务器的并发连接数超过了其承载量,服务器会将其中一些连接关闭;    如果知道实际连接服务器的并发客户数没有超过服务器的承载量,看下有没有网络流量异常。
862 0
|
Web App开发 存储 前端开发
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html><head><meta http-equiv="Cont
NoSuchObjectException(message:There is no database named cloudera_manager_metastore_canary_test_db_hive_hivemetastore_df61080e04cd7eb36c4336f71b5a8bc4) at org.
1082 0
|
Web App开发 前端开发 数据库