实用概念
QNetworkAccessManager
是 Qt 网络模块提供的一个用于发送网络请求和接收网络响应的类。它是一个高层次的网络 API,提供了一种方便的方式来发送和接收 HTTP、FTP 和其他网络协议的数据。QNetworkAccessManager
的主要功能包括:
-
发送网络请求:
QNetworkAccessManager
提供了多种发送网络请求的方法,包括get()
、put()
、post()
、deleteResource()
等。 -
接收网络响应:
QNetworkAccessManager
可以异步接收网络响应,并在响应到达时发出信号。 -
处理网络错误:
QNetworkAccessManager
可以处理网络错误,例如连接超时、网络不可用等。 -
处理网络代理:
QNetworkAccessManager
可以使用网络代理来发送和接收网络请求。
使用QNetworkAccessManager
时,通常需要创建一个QNetworkRequest
对象来描述网络请求的 URL、HTTP 头、请求方法等信息,并将其传递给QNetworkAccessManager
的发送请求方法中。
使用QNetworkAccessManager
时,可以通过连接QNetworkAccessManager
的信号,例如finished()
和sslErrors()
,来处理网络响应和错误。在接收到网络响应时,可以使用QNetworkReply
类来访问响应的 HTTP 头、数据和状态码等信息。
QNetworkReply
是 Qt 网络模块提供的一个用于处理网络响应的类。它提供了访问响应 HTTP 头、数据和状态码等信息的方法,并通过信号和槽机制提供了响应处理的异步方式。
QNetworkReply
的主要功能包括:
-
接收网络响应:
QNetworkReply
可以异步接收网络响应,并在响应到达时发出信号。 -
访问响应数据:
QNetworkReply
提供了多种方法来访问响应数据,例如read()
、readAll()
、bytesAvailable()
等。 -
访问响应 HTTP 头:
QNetworkReply
提供了多种方法来访问响应的 HTTP 头信息,例如header()
、hasRawHeader()
、rawHeaderList()
等。 -
访问响应状态码:
QNetworkReply
提供了方法来访问响应的状态码。
使用QNetworkReply
时,通常需要连接QNetworkReply
的信号,例如readyRead()
和finished()
,来处理响应数据和完成响应处理。在处理响应数据时,可以使用QIODevice
的读取函数来读取数据。在响应处理完成后,需要调用QNetworkReply
的deleteLater()
方法来释放资源。
需要注意的是,由于网络请求和响应的处理是异步的,所以在处理响应时需要注意线程安全和对象生命周期等问题。
接口请求完整步骤
pro 注册
再开始之前,我们需要在项目的 pro 文件内添加网络库
即 QT += core gui network
配置头文件
此处我们需要请求一个天气接口,该接口免费且无需 token 直接使用
天气接口 API: http://t.weather.itboy.net/api/weather/city/101010100
(接口 URL 最末尾的一串数字为城市代码,大家可以上网搜,我这给出的代码是北京的代码)
需要在头文件内定义一些关键性的内容
代码清单 MainWindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QMessageBox>
// 导入必备的两个网络操作库
#include <QNetworkAccessManager>
#include <QNetworkReply>
QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = nullptr);
~MainWindow();
private:
Ui::MainWindow *ui;
protected:
// 获取指定城市代码天气信息的函数
void getWeatherInfo(QString cityCode);
private:
// 当接收到接口传回的响应时,对应的处理函数
void onReplied(QNetworkReply *reply);
private:
// 网络操作对象,用于执行GET或者PUT等基本网络请求
QNetworkAccessManager *networkManager;
};
#endif // MAINWINDOW_H
主体文件
接下来的代码均写在 mainwindow.cpp 里面去
首先应当在构造函数内执行网络管理对象的初始化
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
// 实例化网络管理对象
networkManager = new QNetworkAccessManager(this);
// 配置当接收响应时(QNetworkAccessManager::finished),触发的回调函数onReplied
connect(networkManager,&QNetworkAccessManager::finished,this,&MainWindow::onReplied);
// 设置我们需要获取的天气的城市代码
getWeatherInfo("101010100");
}
看一下获取城市天气信息函数的实现
void MainWindow::getWeatherInfo(QString cityCode)
{
// 配置接口API
QUrl url("http://t.weather.itboy.net/api/weather/city/"+cityCode);
// 直接使用GET请求
networkManager->get(QNetworkRequest(url));
}
对应的响应回调函数的实现
void MainWindow::onReplied(QNetworkReply *reply)
{
qDebug() << "请求成功!!!"; // 输出请求成功的信息
int statusCode = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(); // 获取响应状态码
qDebug() << "状态码:" << statusCode; // 输出状态码
qDebug() << "URL:" << reply->url(); // 输出请求的URL
qDebug() << "操作:" << reply->operation(); // 输出操作类型
qDebug() << "原始头信息:" << reply->rawHeaderList(); // 输出原始头信息
if(reply->error()!=QNetworkReply::NoError||statusCode!=200){ // 如果响应出现错误或状态码不为200
qDebug() << reply->errorString().toLatin1().data(); // 输出错误信息
QMessageBox::critical(this,"错误","无法请求接口,请检查网络是否连接正确",QMessageBox::Ok); // 弹出错误提示框
}else{ // 如果响应正常
QByteArray buff = reply->readAll(); // 读取响应数据
qDebug() << buff.data(); // 输出响应数据
}
reply->deleteLater(); // 释放reply对象
}
此时运行程序,就会发现我们成功的请求了接口,并且获取到了对应数据
下面展示的即为接口回馈的 JSON 信息
{
"message": "success感谢又拍云(upyun.com)提供CDN赞助",
"status": 200,
"date": "20230710",
"time": "2023-07-10 07:42:05",
"cityInfo": {
"city": "北京市",
"citykey": "101010100",
"parent": "北京",
"updateTime": "07:31"
},
"data": {
"shidu": "53%",
"pm25": 12.0,
"pm10": 37.0,
"quality": "优",
"wendu": "29",
"ganmao": "各类人群可自由活动",
"forecast": [
{
"date": "10",
"high": "高温 39℃",
"low": "低温 27℃",
"ymd": "2023-07-10",
"week": "星期一",
"sunrise": "04:55",
"sunset": "19:44",
"aqi": 91,
"fx": "东北风",
"fl": "2级",
"type": "多云",
"notice": "阴晴之间,谨防紫外线侵扰"
},
{
"date": "11",
"high": "高温 35℃",
"low": "低温 28℃",
"ymd": "2023-07-11",
"week": "星期二",
"sunrise": "04:55",
"sunset": "19:44",
"aqi": 97,
"fx": "东南风",
"fl": "2级",
"type": "多云",
"notice": "阴晴之间,谨防紫外线侵扰"
},
{
"date": "12",
"high": "高温 31℃",
"low": "低温 25℃",
"ymd": "2023-07-12",
"week": "星期三",
"sunrise": "04:56",
"sunset": "19:43",
"aqi": 78,
"fx": "东风",
"fl": "1级",
"type": "中雨",
"notice": "记得随身携带雨伞哦"
},
{
"date": "13",
"high": "高温 34℃",
"low": "低温 24℃",
"ymd": "2023-07-13",
"week": "星期四",
"sunrise": "04:57",
"sunset": "19:43",
"aqi": 91,
"fx": "西南风",
"fl": "2级",
"type": "小雨",
"notice": "雨虽小,注意保暖别感冒"
},
{
"date": "14",
"high": "高温 34℃",
"low": "低温 24℃",
"ymd": "2023-07-14",
"week": "星期五",
"sunrise": "04:57",
"sunset": "19:43",
"aqi": 98,
"fx": "西北风",
"fl": "3级",
"type": "晴",
"notice": "愿你拥有比阳光明媚的心情"
},
{
"date": "15",
"high": "高温 35℃",
"low": "低温 25℃",
"ymd": "2023-07-15",
"week": "星期六",
"sunrise": "04:58",
"sunset": "19:42",
"aqi": 69,
"fx": "西北风",
"fl": "3级",
"type": "晴",
"notice": "愿你拥有比阳光明媚的心情"
},
{
"date": "16",
"high": "高温 36℃",
"low": "低温 22℃",
"ymd": "2023-07-16",
"week": "星期日",
"sunrise": "04:59",
"sunset": "19:41",
"aqi": 60,
"fx": "东北风",
"fl": "2级",
"type": "晴",
"notice": "愿你拥有比阳光明媚的心情"
},
{
"date": "17",
"high": "高温 37℃",
"low": "低温 23℃",
"ymd": "2023-07-17",
"week": "星期一",
"sunrise": "05:00",
"sunset": "19:41",
"aqi": 59,
"fx": "东南风",
"fl": "2级",
"type": "晴",
"notice": "愿你拥有比阳光明媚的心情"
},
{
"date": "18",
"high": "高温 39℃",
"low": "低温 25℃",
"ymd": "2023-07-18",
"week": "星期二",
"sunrise": "05:01",
"sunset": "19:40",
"aqi": 85,
"fx": "东风",
"fl": "2级",
"type": "小雨",
"notice": "雨虽小,注意保暖别感冒"
},
{
"date": "19",
"high": "高温 38℃",
"low": "低温 24℃",
"ymd": "2023-07-19",
"week": "星期三",
"sunrise": "05:01",
"sunset": "19:40",
"aqi": 77,
"fx": "东风",
"fl": "2级",
"type": "晴",
"notice": "愿你拥有比阳光明媚的心情"
},
{
"date": "20",
"high": "高温 39℃",
"low": "低温 25℃",
"ymd": "2023-07-20",
"week": "星期四",
"sunrise": "05:02",
"sunset": "19:39",
"aqi": 54,
"fx": "东南风",
"fl": "2级",
"type": "小雨",
"notice": "雨虽小,注意保暖别感冒"
},
{
"date": "21",
"high": "高温 36℃",
"low": "低温 23℃",
"ymd": "2023-07-21",
"week": "星期五",
"sunrise": "05:03",
"sunset": "19:38",
"aqi": 65,
"fx": "东南风",
"fl": "2级",
"type": "多云",
"notice": "阴晴之间,谨防紫外线侵扰"
},
{
"date": "22",
"high": "高温 38℃",
"low": "低温 25℃",
"ymd": "2023-07-22",
"week": "星期六",
"sunrise": "05:04",
"sunset": "19:37",
"aqi": 47,
"fx": "东风",
"fl": "2级",
"type": "中雨",
"notice": "记得随身携带雨伞哦"
},
{
"date": "23",
"high": "高温 38℃",
"low": "低温 24℃",
"ymd": "2023-07-23",
"week": "星期日",
"sunrise": "05:05",
"sunset": "19:37",
"aqi": 49,
"fx": "北风",
"fl": "2级",
"type": "暴雨",
"notice": "关好门窗,外出避开低洼地"
},
{
"date": "24",
"high": "高温 30℃",
"low": "低温 21℃",
"ymd": "2023-07-24",
"week": "星期一",
"sunrise": "05:06",
"sunset": "19:36",
"aqi": 46,
"fx": "东北风",
"fl": "1级",
"type": "中雨",
"notice": "记得随身携带雨伞哦"
}
],
"yesterday": {
"date": "09",
"high": "高温 38℃",
"low": "低温 25℃",
"ymd": "2023-07-09",
"week": "星期日",
"sunrise": "04:54",
"sunset": "19:45",
"aqi": 101,
"fx": "西北风",
"fl": "2级",
"type": "多云",
"notice": "阴晴之间,谨防紫外线侵扰"
}
}
}
完整代码结构
头文件 MainWindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QMessageBox>
#include <QNetworkAccessManager>
#include <QNetworkReply>
QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = nullptr);
~MainWindow();
private:
Ui::MainWindow *ui;
protected:
void getWeatherInfo(QString cityCode);
private:
void onReplied(QNetworkReply *reply);
private:
QNetworkAccessManager *networkManager;
};
#endif // MAINWINDOW_H
主文件 MainWindow.cpp
#include "MainWindow.h"
#include "ui_MainWindow.h"
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
networkManager = new QNetworkAccessManager(this);
connect(networkManager,&QNetworkAccessManager::finished,this,&MainWindow::onReplied);
getWeatherInfo("101010100");
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::getWeatherInfo(QString cityCode)
{
QUrl url("http://t.weather.itboy.net/api/weather/city/"+cityCode);
networkManager->get(QNetworkRequest(url));
}
void MainWindow::onReplied(QNetworkReply *reply)
{
qDebug() << "request successfully!!!";
int statusCode = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
qDebug() << "status code:" << statusCode;
qDebug() << "url:" << reply->url();
qDebug() << "operation:" << reply->operation();
qDebug() << "raw header:" << reply->rawHeaderList();
if(reply->error()!=QNetworkReply::NoError||statusCode!=200){
qDebug() << reply->errorString().toLatin1().data();
QMessageBox::critical(this,"错误","无法请求接口,请检查网络是否连接正确",QMessageBox::Ok);
}else{
QByteArray buff = reply->readAll();
qDebug() << buff.data();
}
reply->deleteLater();
}