上节编程所使用的QUdpSocket、QTcpSocket和QTepServer类都是网络传输层上的类,它们封装实现的是低层的网络进程通信(Socket通信)的功能。
应用层的网络协议(如HTTP/FTP/SMTP等)简称“应用协议”,它们运行在TCP/UDP之上,如图下图所示。
Qt 4以前的版本提供QHttp类用于构建HTTP客户端,提供QFtp类用于FTP客户端的开发。
从Qt 5开始,已不再分别提供QHttp类、QFtp 类,应用层的编程使用QNetworkRequest、 QNetworkReply 和
QNetworkAccessManager这几个高层次的类代替,它们提供了更加简单和强大的接口。
网络请求由QNetworkRequest类来表示,作为与请求有关的信息的统一容器,在创建请求对象时指定的URL决定了请求
使用的协议,目前支持HTTP、FTP和本地文件URLs的.上传和下载;
QNetworkAceessManager 类用于协调网络操作,每当一个请求创建后,该类用来调度它,并发射信号来报告进度;而对
于网络请求的应答则使用QNetworkReply类表示,它会在请求被完成调度时由QNetworkAccessManager创建。
**(1)、新建Qt Gui应用,名称为“ myHTTP”,类名为“MainWindow”,基类保持"QMainWindow”不变。**完成后先在
“myHTTP.pro”文件中添加语句“QT+= netwotk",并保存该文件。进入设计模式,向界面上拖入一个Text Browser, 然后进
入"mainwindow.h"文件,首先添加类的前置声明:
class QNetworkReply; class QNetworkAccessManager; QNetworkAccessManager *manager; private slots: void replyFinished(QNetworkReply *);添加头文件:
#include <QtNetwork> #include <QUrl>(2)、在“mainwindow.cpp"文件中,首先添加头文件:
#include <QtNetwork>然后在构造函数中添加如下代码:
manager = new QNetworkAccessManager(this); connect(manager,SIGNAL(finished(QNetworkReply*)),this,SLOT(replyFinished(QNetworkReply*))); manager->get(QNetworkRequest(QUrl("http://www.baidu.com")));这里首先创建了–个QNetworkAccessManager类的实例,它用来发送网络请求和接收应答。然后关联了管理器的
finished()信号和自定义的槽,每当网络应答结束时都会发射这个信号。最后使用了get()函 数来发送一个网络请求,网
络请求使用QNetworkRequest类表示,get()函 数返回一个QNetworkReply对象。
(3)、下面添加槽的定义:
void MainWindow::replyFinished(QNetworkReply *reply) { QString all = reply->readAll(); ui->textBrowser->setText(all); reply->deleteLater(); }因为QNetworkReply继承自QIODevice类,所以可以像操作一般的I/O设备一样操作该类。这里使用了readAll()函数来读
取所有的应答数据。在完成数据的读取后,需要使用deleteLater()删除reply对象。
(4)、运行程序,显示出“百度搜索”首页。
(1)、在网页浏览实例的基础上,实现一般页面文件的下载,并且显示下载进度。
进入设计模式,向界面上拖入Label、Line Edit、Progress Bar和Push Button等部件,
界面设计完成后,效果如下图所示。 (2)、在“mainwindow.h”文件中,添加头文件和类的前置声明:
#include <QUrl> class QFile;其次添加如下私有槽声明:
void httpFinished(); void httpReadyRead(); void updateDataReadProgress(qint64,qint64); void on_pushButton_clicked();然后再添加一个public函数声明:
void startRequest(QUrl url);最后添加几个私有对象定义:
QNetworkReply *reply; QUrl url; QFile *file;(3)、在“mainwindow.cpp"文件中,在构造函数中添加:
ui->progressBar->hide();这里开始将进度条隐藏了,因此在没有下载文件时是不显示进度条的。
(4)、接下来添加几个新函数,首先先添加网络请求函数的实现:
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())); }这里使用了get()函数发送网络请求,进行了QNetworkReply 对象的几个信号和自定义槽的关联。其中,readyRead()信
号继承自QIODevice类,每当有新的数据可以读取时,都会发射该信号:每当网络请求的下载进度更新时都会发射
downloadProgress()信号,用于更新进度条;每当应答处理结束时,都会发射finished()信号,该信号与前面程序中
QNetworkAccessManager类的finished()信号作用相同,只不过是发送者不同,参数也不同而已。
(5)、下面添加几个槽的定义:
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::httpFinished() { ui->progressBar->hide(); file->flush(); file->close(); reply->deleteLater(); reply = 0; delete file; file = 0; }当完成下载后,重新隐藏进度条,删除reply和file 对象。
(6)、进入设计模式,进入“下载”按钮的单击信号的槽,添加如下代码:
void MainWindow::on_pushButton_clicked() { url = ui->lineEdit->text(); QFileInfo info(url.path()); QString fileName(info.fileName()); 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(); }这里使用要下载的文件名创建了本地文件,使用输入的url 进行网络请求,并显示进度条。
(7)、运行程序,可以输入-一个网络文件地址,单击“下载”按钮将其下载到本地。
例如,下载华军软件园上的软件“Internet Download Manager”。
使用如下URL地址: https://www.onlinedown.net/soft/2729.htm
下载过程中,进度条的动态变化如下图所示: 等待进度条走完后,便下载结束,会在项目的build-myHTTP-Desktop_Qt_5_13_2_MSVC2017_64bit-Debug目录中得到下载的文件。