Http
Http(HyperText Transfer Protocol,超文本传输协议) 是一个客户端和服务器端之间进行请求和应答的标准。通常由Http客户端发起一个请求,建立一个到服务器指定端口(默认是80端口)的Tcp连接;Http服务器在指定的端口监听客户端发送过来的请求,一旦收到请求,服务器端就会向客户端发回一个应答。
几个常用类的介绍:
- QNetworkAccessManager:它用来发送网络请求和接收应答。发送请求的函数有get()、post()、put()等等。发送请求的函数都会返回一个QNetworkReply应答对象。
- QNetworkReply:继承自QIODevice类,所以可以像操作一般的I/O设备一样操作该类。一般常见的用法就是使用readAll()函数来读取所有的应答数据,完成数据的读取之后需要使用deleteLater()来删除reply对象。
- QNetworkRequest:网络请求对象,一般作为QNetworkAccessManager对象发送请求网络请求的参数。
- QUrl:请求的url地址,一般作为QNetworkRequest构造参数。
(上述几个类的简单的用法见下面的例子,详细的用法请参见qt帮助文档)
一个基本的网络请求例子:将请求的内容显示到一个文本输入框内
//.pro
QT += network
//mainwindow.h
#include <QMainWindow>
QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE
//添加类的前置声明
class QNetworkReply;
class QNetworkAccessManager;
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = nullptr);
~MainWindow();
private:
Ui::MainWindow *ui;
QNetworkAccessManager* manager;
private slots:
void replyFinished(QNetworkReply *);
};
//mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QtNetwork>
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
manager = new QNetworkAccessManager(this);
connect(manager,&QNetworkAccessManager::finished,this,&MainWindow::replyFinished);
manager->get(QNetworkRequest(QUrl("http://www.qter.org")));
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::replyFinished(QNetworkReply *reply)
{
QString all = reply->readAll();
ui->lineEdit->setText(all);
reply->deleteLater();
}
演示结果:
简单的文件下载操作
演示代码:
//.pro
QT += network
//mainwindow.h
#include <QMainWindow>
#include <QtNetwork>
QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE
class QFile;
class QNetworkReply;
class QNetworkAccessManager;
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = nullptr);
~MainWindow();
void startRequest(QUrl url);
private:
Ui::MainWindow *ui;
QNetworkAccessManager* manager;
QNetworkReply* reply;
QUrl url;
QFile* file;
private slots:
void httpFinished();
void httpReadyRead();
void updateDataReadProgress(qint64,qint64);
void on_pushButton_clicked();
};
//mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QDebug>
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
manager = new QNetworkAccessManager(this);
ui->progressBar->hide();//初始时,隐藏进度条
}
MainWindow::~MainWindow()
{
delete ui;
}
//开始发请求
void MainWindow::startRequest(QUrl url)
{
reply = manager->get(QNetworkRequest(url)); //发送get请求
connect(reply,&QNetworkReply::readyRead,this,&MainWindow::httpReadyRead); //每当有新数据可读时都会发出此信号
connect(reply,&QNetworkReply::downloadProgress,this,&MainWindow::updateDataReadProgress); //每当网络请求的下载进度更新时都会发出此信号
connect(reply,&QNetworkReply::finished,this,&MainWindow::httpFinished);//每当应答处理结束时都会发出此信号
}
//下载完成
void MainWindow::httpFinished()
{
ui->progressBar->hide(); //下载结束,隐藏进度条
// qDebug() << file->fileName();
if(file){
file->close();
delete file;
file = 0;
}
reply->deleteLater();
reply = 0;
}
void MainWindow::httpReadyRead()
{
if(file)
file->write(reply->readAll()); //如果文件存在则写入文件
}
//更新进度条
void MainWindow::updateDataReadProgress(qint64 bytesRead, qint64 totalBytes)
{
ui->progressBar->setMaximum(totalBytes);
ui->progressBar->setValue(bytesRead);
}
//点击下载
void MainWindow::on_pushButton_clicked()
{
url = ui->lineEdit->text();
qDebug() << url.path();
QFileInfo info(url.path());
QString fileName(info.fileName());
// qDebug() << info.path();
if(fileName.isEmpty())fileName = "index.html";
fileName.prepend("/Users/liucan/Desktop/"); //下载完之后,文件的位置
file = new QFile(fileName);
if(!file->open(QIODevice::WriteOnly)){ //以只写方式打开文件
qDebug() << file->errorString();
delete file;
file = 0;
return ;
}
startRequest(url); //开始请求下载
ui->progressBar->setValue(0);
ui->progressBar->show();
}
运行程序,输入下载文件的url地址,点击下载可以看看效果
演示效果:
HTTP小总结:
- 读新数据时候,根据
QNetworkReply::readRead()
信号关联对应的槽函数,并在槽函数中使用QNetworkReply::readAll()
方法读取数据到某个设备之中。 - 若需要知道请求(下载)的进度,根据
QNetworkReply::downloadProgress(qint64 bytesReceived, qint64 bytesTotal)
信号关联对应的槽函数显示请求进度,bytesReceived
是接收到的数据,bytesTotal
是期望接收到的总数据。 - 在请求完成的时候,根据
QNetworkReply::finished()
信号关联到对应的槽函数,进行一些资源释放操作(很重要)
- 若请求的过程有
ssl
错误发生,想知道错误信息,可以关联QNetworkReply::sslErrors(const QList<QSslError> &errors)
信号,打印错误信息,也可以调用QNetworkReply::ignoreSslErrors()
来忽略错误,但可能会给你的应用程序带来风险。 - 若请求需要提供身份认证信息,关联
QNetworkAccessManager::authenticationRequired(QNetworkReply *, QAuthenticator *authenticator)
信号,通过QAuthenticator::setUser(const QString &)
和QAuthenticator::setPassword(const QString &)
提供身份信息