目录
一、注意事项和重要代码
1、使用场景
2、发送请求的方式有两种
3、使用前提
4、get主要代码
5、post第一种主要代码
6、post第二种主要代码
二、详细代码
三、结果图
qt,需要对服务器发送请求(包含报文),并接收服务器的返回值;服务器用的是mongoose模拟的服务器;
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");
一定要注意!!!!!,不然无法与服务器连接
在.pro文件中添加
QT += network
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);
}
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);
}
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