【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定义更改为

 
  1. void startRequest(const QString &hostName,

  2. const QString &diskName,

  3. const QString &diskSize,

  4. const QString &mount,

  5. const QString &format,

  6. const QString &authStatus,

  7. 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主要代码

 
  1. void MainWindow::startRequest(const QUrl &requestedUrl){

  2. url = requestedUrl;

  3. manager = new QNetworkAccessManager(this);

  4. req.setUrl(url);

  5. //由于请求发生重定向,所以要加上这行代码,设置自动跳转,否则会返回 302

  6. req.setAttribute(QNetworkRequest::FollowRedirectsAttribute, true);

  7. reply = manager->get(req);

  8. connect(reply,&QNetworkReply::finished,this,&MainWindow::replyFinished);

  9.  
  10. }

5、post第一种主要代码

 
  1. void MainWindow::startRequest(const QUrl &requestedUrl){

  2. url = requestedUrl;

  3. //post

  4. QByteArray array;

  5. json.insert("table_operation","select");

  6. QJsonDocument document;

  7. document.setObject(json);

  8. array = document.toJson(QJsonDocument::Compact);

  9. qDebug()<<"array在转为json后为:"<<array;

  10.  
  11. manager = new QNetworkAccessManager(this);

  12. req.setUrl(url);

  13. req.setHeader(QNetworkRequest::ContentTypeHeader,QVariant("application/json"));

  14. req.setAttribute(QNetworkRequest::FollowRedirectsAttribute, true);

  15. reply = manager->post(req,array);

  16. connect(reply,&QNetworkReply::finished,this,&MainWindow::replyFinished);

  17. }

6、post第二种主要代码

 
  1. void MainWindow::sendRequest(const QString &hostName,

  2. const QString &diskName,

  3. const QString &diskSize,

  4. const QString &mount,

  5. const QString &format,

  6. const QString &authStatus,

  7. const QString &keyfile)

  8. {

  9. //1.json格式传输报文

  10. QJsonObject json;

  11. QJsonDocument jsonDoc;

  12.  
  13. //打包json数据

  14. json["host_name"] = hostName;

  15. json["disk_name"] = diskName;

  16. json["disk_size"] = diskSize;

  17. json["mount"] = mount;

  18. json["format"] = format;

  19. json["certification_status"] = authStatus;

  20. json["keyfile_path"] = keyfile;

  21.  
  22. jsonDoc.setObject(json);

  23. QByteArray dataArray = jsonDoc.toJson(QJsonDocument::Compact);

  24. qDebug()<< "jsondata组为:"<<dataArray;

  25.  
  26. //2.构造URL&&请求头

  27. QString urlStr = "http://127.0.0.1:8000/test";

  28. qDebug()<<"url地址为:"<<urlStr;

  29. url = urlStr;

  30. //构造请求头

  31. req.setUrl(url);

  32. req.setHeader(QNetworkRequest::ContentTypeHeader,QVariant("application/json;charset=UTF-8"));

  33. // req.setRawHeader("Connection", "Keep-Alive");

  34.  
  35. //3.post数据

  36. manager = new QNetworkAccessManager(this);

  37. reply = manager->post(req,dataArray);

  38. QEventLoop eventLoop;

  39. connect(manager,SIGNAL(finished(QNetworkReply*)),&eventLoop,SLOT(quit()));

  40. connect(reply,&QNetworkReply::finished,this,&MainWindow::replyFinished);

  41. eventLoop.exec();

  42. }

二、详细代码

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

1、mainwindow.h

 
  1. #ifndef MAINWINDOW_H

  2. #define MAINWINDOW_H

  3.  
  4. #include <QMainWindow>

  5. #include <QDebug>

  6. #include <QtNetwork>

  7. #include <QNetworkAccessManager>

  8. #include <QNetworkReply>

  9. #include <QNetworkRequest>

  10. #include <QTextCodec>

  11. #include <QFile>

  12. #include <QTextStream>

  13. #include <QDateTime>

  14.  
  15. QT_BEGIN_NAMESPACE

  16. namespace Ui { class MainWindow; }

  17. QT_END_NAMESPACE

  18.  
  19. class MainWindow : public QMainWindow

  20. {

  21. Q_OBJECT

  22.  
  23. public:

  24. MainWindow(QWidget *parent = nullptr);

  25. ~MainWindow();

  26. void startRequest(const QUrl &requestedUrl);

  27.  
  28. private:

  29. Ui::MainWindow *ui;

  30.  
  31. private:

  32. // [3] 添加对象

  33. QUrl url;

  34. QNetworkRequest req;

  35. QNetworkReply *reply;

  36. QNetworkAccessManager *manager;

  37.  
  38. private slots:

  39. // void startRequest(const QUrl &requestedUrl);

  40. void replyFinished();

  41.  
  42. };

  43. #endif // MAINWINDOW_H

2、mainwindow.cpp

 
  1. #include "mainwindow.h"

  2. #include "ui_mainwindow.h"

  3. #include <QLabel>

  4.  
  5. MainWindow::MainWindow(QWidget *parent)

  6. : QMainWindow(parent)

  7. , ui(new Ui::MainWindow)

  8. {

  9. ui->setupUi(this);

  10. //调用函数发送请求,参数是请求的服务器地址

  11. startRequest( QUrl("http://127.0.0.1:8000/test"));

  12.  
  13. }

  14.  
  15. MainWindow::~MainWindow()

  16. {

  17. delete ui;

  18. }

  19.  
  20. void MainWindow::startRequest(const QUrl &requestedUrl){

  21. url = requestedUrl;

  22. manager = new QNetworkAccessManager(this);

  23. req.setUrl(url);

  24. //由于请求发生重定向,所以一定要加上这行代码,设置自动跳转,否则会返回 302

  25. req.setAttribute(QNetworkRequest::FollowRedirectsAttribute, true);

  26. // 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");

  27. // 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");

  28. //get方式发送请求

  29. reply = manager->get(req);

  30. //将服务器的返回信号与replyFinished槽连接起来,当服务器返回消息时,会在槽里做相应操作

  31. connect(reply,&QNetworkReply::finished,this,&MainWindow::replyFinished);

  32.  
  33. }

  34.  
  35. void MainWindow::replyFinished(){

  36.  
  37. // <1>判断有没有错误

  38. if (reply->error()){

  39. qDebug()<<reply->errorString();

  40. reply->deleteLater();

  41. return;

  42. }

  43.  
  44. // <2>检测网页返回状态码,常见是200,404等,200为成功

  45. int statusCode = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();

  46. qDebug() << "statusCode:" << statusCode;

  47.  
  48. // <3>判断是否需要重定向

  49. if (statusCode >= 200 && statusCode <300){

  50. // ok

  51.  
  52. // 准备读数据

  53. QTextCodec *codec = QTextCodec::codecForName("utf8");

  54. QString all = codec->toUnicode(reply->readAll());

  55. qDebug() << "接收到的数据" <<all;

  56.  
  57. //显示在mainwindow 测试,将服务器返回值打印至label上,服务器用的是mongoose模拟

  58. QLabel *label = new QLabel(this);

  59. label->setText(all);

  60. label->move(200,200);

  61. label->setVisible(true);

  62.  
  63. // 数据读取完成之后,清除reply

  64. reply->deleteLater();

  65. reply = nullptr;

  66.  
  67. } else if (statusCode >=300 && statusCode <400){

  68. // redirect

  69.  
  70. // 获取重定向信息

  71. const QVariant redirectionTarget = reply->attribute(QNetworkRequest::RedirectionTargetAttribute);

  72. // 检测是否需要重定向,如果不需要则读数据

  73. if (!redirectionTarget.isNull()) {

  74. const QUrl redirectedUrl = url.resolved(redirectionTarget.toUrl());

  75.  
  76. reply->deleteLater();

  77. reply = nullptr;

  78.  
  79. startRequest(redirectedUrl);

  80. qDebug()<< "http redirect to " << redirectedUrl.toString();

  81. return;

  82. }

  83. }

  84. }

3、main.cpp

 
  1. #include "mainwindow.h"

  2. #include <QApplication>

  3. int main(int argc, char *argv[])

  4. {

  5. QApplication a(argc, argv);

  6. MainWindow w;

  7. w.show();

  8. return a.exec();

  9. }

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

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

三、结果图

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

20210721105024909.png

20210721140826796.png

 

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

20210721105159581.png

四、参考

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

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

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

 

##END

  • 5
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值