HTTP协议
以下来自维基百科
超文本传输协议(英语:HyperText Transfer Protocol,缩写:HTTP)是一种用于分布式、协作式和超媒体信息系统的应用层协议[1]。HTTP是万维网的数据通信的基础。
设计HTTP最初的目的是为了提供一种发布和接收HTML页面的方法。通过HTTP或者HTTPS协议请求的资源由统一资源标识符(Uniform Resource Identifiers,URI)来标识。
在Qt网络编程简介中我们提到过Qt中使用QNetworkAccessManager类和QNetworkReply类来进行HTTP的编程。网络请求由QNetworkRequest类来表示,它也作为与请求有关的信息(例如,任何头信息和使用加密)的容器。
在创建请求对象时指定的URL决定了请求使用的协议,目前支持HTTP、FTP和本地文件URLs的上传和下载。QNetworkAccessManager类用来协调网络操作,每当一个请求创建后,该类用来调度它,并发射信号来报告进度。该类还协调cookies的使用,身份验证请求,及其代理的使用等。对于网络请求的应答使用QNetworkReply类表示,它会在请求被完成调度时由QNetworkAccessManager来创建。QNetworkReply提供的信号可以用来单独的监视每一个应答。
QT 中实现网页浏览功能(QT4.8 或者5.8 都行)
-
新建一个gui 项目,如下图, 在por文件中加上
QT += core gui network
。 -
在ui文件中放一个
Text Browser
部件
-
然后.h 文件如下:
QtNetwork
是网络总的头文件
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QtNetwork>
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
private slots:
void ReplyFinished(QNetworkReply*);
private:
Ui::MainWindow *ui;
QNetworkAccessManager* m_manager{nullptr};
};
#endif // MAINWINDOW_H
- cpp文件如下:
#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
m_manager = new QNetworkAccessManager(this);
/// 创建了一个QNetworkAccessManager类的实例,它用来发送网络请求和接收
/// 应答。然后关联了管理器的finished()信号和我们自定义的槽,每当网络应答结束时都会发射这个信号。
connect(m_manager, SIGNAL(finished(QNetworkReply*)), this, SLOT(ReplyFinished(QNetworkReply*)));
// connect(m_manager, &QNetworkAccessManager::finished(QNetworkReply*), this, [this]{
// ReplyFinished(QNetworkReply* reply);
// });
/// 最后使用了get()函数来发送一个网络请求,网络请求使用QNetworkRequest类表示,get()函数返回一个QNetworkReply对象
m_manager->get(QNetworkRequest(QUrl("http://www.shanghai.gov.cn/")));
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::ReplyFinished(QNetworkReply *reply)
{
QTextCodec *codec = QTextCodec::codecForName("utf8");
QString all = codec->toUnicode(reply->readAll());
ui->textBrowser->setText(all);
reply->deleteLater();
}
- 这里先创建了一个
QNetworkAccessManager
类的实例,它用来发送网络请求和接收应答。然后关联了管理器的finished()
信号和我们自定义的槽,每当网络应答结束时都会发射这个信号。
最后使用了get()
函数来发送一个网络请求,网络请求使用QNetworkRequest
类表示,get()
函数返回一个QNetworkReply
对象。除了get()函数,管理器还提供了发送HTTP 的POST请求的post()
函数。 QNetworkReply
继承自QIODevice
类,所以可以操作一般的I/O设备一样来操作该类。- 这里使用了
readAll()
函数来读取所有的应答数据,为了正常显示中文,使用了QTextCodec
类来转换编码。在完成数据的读取后,需要使用deleteLater()
来删除replay对象。
下面是程序运行的结果,(上海政府的一个网页), 在上面没有加上ssl,所有访问https是有问题。
这里再将整个过程简答叙述一遍:上面实现了最简单的应用HTTP协议下载网页的功能。QNetworkAccessManager
类用于发送网络请求和接受回复,具体来说,它是用QNetworkRequest
类来管理请求,QNetworkReply
类进行接收回复,并对数据进行处理。
在上面的代码中,我们使用了下面的代码来发送请求:
manager->get(QNetworkRequest(QUrl("http://www.shanghai.gov.cn/")));
它返回一个QNetworkReply对象,这个后面再讲。我们只需知道只要发送请求成功,它就会下载数据。而当数据下载完成后,m_manager
会发出finished()
信号,我们关联了该信号:
connect(m_manager, SIGNAL(finished(QNetworkReply*)),
this,SLOT(replyFinished(QNetworkReply*)));
也就是说,当下载数据结束时,就会执行replyFinished()
函数。在这个函数中我们对接收的数据进行处理:
QTextCodec *codec = QTextCodec::codecForName("utf8");
QString all = codec->toUnicode(reply->readAll());
ui->textBrowser->setText(all);
这里,为了能显示下载的网页中的中文,我们使用了QTextCodec
类对象,应用utf8编码。使用reply->readAll()
函数就可以将下载的所有数据读出。然后,我们在textBrowser
中将数据显示出来。当reply
对象已经完成了它的功能时,我们需要将它释放,就是最后一条代码:
reply->deleteLater();
QT 实现下载文件功能
介绍一下整个程序执行的流程:开始我们先让进度条隐藏。当我们在Line
Edit中输入下载地址,点击下载按钮后,我们应用输入的下载地址,获得文件名,在磁盘上新建一个文件,用于保存下载的数据,然后进行链接,并显示进度条。在下载过程中,我们将每次获得的数据都写入文件中,并更新进度条,在接收完文件后,我们重新隐藏进度条,并做一些清理工作。根据这个思路,我们开始代码的编写。
.h 文件
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QtNetwork>
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
void startRequest(QUrl url); //请求链接
private slots:
void on_pushButton_clicked(); //下载按钮的单击事件槽函数
void httpFinished(); //完成下载后的处理
void httpReadyRead(); //接收到数据时的处理
void updateDataReadProgress(qint64, qint64); //更新进度条
private:
Ui::MainWindow *ui;
QNetworkReply *reply;
QUrl url; //存储网络地址
QFile *file; //文件指针
QNetworkAccessManager* manager;
};
#endif // MAINWINDOW_H
.cpp 文件
#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
manager = new QNetworkAccessManager(this);
ui->progressBar->hide();
connect(ui->pushButton, SIGNAL(clicked), this, SLOT(on_pushButton_clicked()));
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::startRequest(QUrl url)
{
reply = manager->get(QNetworkRequest(url));
connect(reply, SIGNAL(readyRead()), this, SLOT(httpReadyRead()));
connect(reply, SIGNAL(downloadProgress(qint64, qint64)),
this, SLOT(updateDataReadProgress(qint64, qint64)));
connect(reply, SIGNAL(finished()), this, SLOT(httpFinished()));
}
void MainWindow::on_pushButton_clicked()
{
url = ui->lineEdit->text();
QFileInfo info(url.path());
QString fileName(info.fileName());
if (fileName.isEmpty()) fileName = "index.html";
file = new QFile(fileName);
if(!file->open(QIODevice::WriteOnly))
{
qDebug() << "file open error";
delete file;
file = 0;
return;
}
startRequest(url);
ui->progressBar->setValue(0);
ui->progressBar->show();
}
void MainWindow::httpFinished()
{
ui->progressBar->hide();
file->flush();
file->close();
reply->deleteLater();
reply = 0;
delete file;
file = 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);
}
httpReadyRead
函数中,先判断是否创建了文件,如果是,则读取返回的所有数据,然后写入到文件。该文件是在后面的“下载”按钮单击信号槽中创建并打开的。
updateDataReadProgress
函数设置了一下进度条的最大值和当前值。
执行后的结果:
总结: 上面就是HTTP 的两个简单例子,后续会更新FTP,TCP ,敬请期待~