目录
一、注意事项和重要代码
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