您现在的位置是:网站首页> C/C++

Qt6 C++ 网络请求实例

  • C/C++
  • 2023-07-22
  • 618人已阅读
摘要

实用概念

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();

}



Top