1 获取本机网络与通信
在网络应用中,经常需要获得本机的主机名.IP地址和硬件地址等网络信息.运用QHostInfo,QNetWorkInterface,QNetworkAddressEntry可获得本机的网络信息.
widget.h
#ifndef WIDGET_H
#define WIDGET_H
#include
#include
#include
#include
#include
#include
#include
#include
namespace Ui {
class Widget;
}
class Widget : public QWidget
{
Q_OBJECT
public:
explicit Widget(QWidget *parent = );
~Widget();
private:
QLabel *hostLabel;
QLineEdit *LineEditLocalHostName;
QLabel *ipLabel;
QLineEdit *LineEditAddress;
QPushButton \*detailBtn;
QGridLayout \*mainLayout;
private:
Ui::Widget *ui;
public:
void getHostInformation();
public slots:
void slotDetail();
};
#endif // WIDGET_H
widget.cpp
#include "widget.h"
#include "ui_widget.h"
Widget::Widget(QWidget *parent) :
QWidget(parent),
ui(new Ui::Widget)
{
ui->setupUi(this);
hostLabel = new QLabel(tr("主机名: "));
LineEditLocalHostName = new QLineEdit;
ipLabel = new QLabel(tr("IP 地址:"));
LineEditAddress = new QLineEdit;
detailBtn = new QPushButton(tr("详细"));
mainLayout = new QGridLayout(this);
mainLayout->addWidget(hostLabel,,);
mainLayout->addWidget(LineEditLocalHostName,,);
mainLayout->addWidget(ipLabel,,);
mainLayout->addWidget(LineEditAddress,,);
//第二行第0个,占两列
mainLayout->addWidget(detailBtn,,,,);
getHostInformation();
connect(detailBtn,SIGNAL(clicked(bool)),this,SLOT(slotDetail()));
}
Widget::~Widget()
{
delete ui;
}
void Widget::getHostInformation()
{
//获得本机主机名.QHostInfo提供了一系列有关网络信息的静态函数,
//可以根据主机名获得分配的IP地址,也可以根据IP地址获得相应的主机名
**37 QString localHostName = QHostInfo::localHostName();
** LineEditLocalHostName->setText(localHostName);
//根据主机名获得相关主机信息,包括IP地址等.
//QHostInfo::fromName()函数通过主机名查找IP地址信息
42 QHostInfo hostInfo = QHostInfo::fromName(localHostName);
//获得主机的IP地址列表
QList
//在不为空的情况下,使用第一个IP地址
if(!listAddress.isEmpty())
{
LineEditAddress->setText(listAddress.first().toString());
}
}
void Widget::slotDetail()
{
QString detail="";
//QNetworkInterface类提供了一个IP地址和网络接口的列表
QList
for(int i=;i<list.count();i++)
{
QNetworkInterface interface=list.at(i); //获得网络接口的名称
**detail=detail+tr("设备: ")+interface.name()+"\\n"; </code></pre>
** //获得网络接口的名称
detail=detail+tr("硬件地址:")+interface.hardwareAddress()+"\n";
//每个网络接口包括0个或多个IP地址,
//每个IP地址有选择性地与一个子网掩码和一个广播地址相关联
//QNetworkAddressEntry类存储了被网络接口支持的一个IP地址,
//同时还包括与之相关的子网掩码和广播地址
**73 QList entryList=interface.addressEntries();
**
for(int j=;j<entryList.count();j++)
{
QNetworkAddressEntry entry = entryList.at(j);
detail=detail+"\\t"+tr("IP地址: ")+entry.ip().toString()+"\\n";
detail=detail+"\\t"+tr("子网掩码: ")+entry.netmask().toString()+"\\n";
detail=detail+"\\t"+tr("广播地址: ")+entry.broadcast().toString()+"\\n";
}
QMessageBox::information(this,tr("Detail"),detail);
}
}
main.cpp
#include "widget.h"
#include
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
Widget w;
w.show();
return a.exec();
}
2 基于UDP的网络广播程序
2.1 UDP(user data protocol)是一种简单轻量级,不可靠,面向数据报无连接的传输协议,可以用在不是十分重要的场合
2.2 UDP编程模型
在UDP方式下客户端并不与服务器建立连接,它只负责调用发送函数向服务器法术数据报.类似的服务器不从客户端接收连接,只负责调用接收函数,等待来自某客户端的数据到达.Qt中通过QUdpSocket类实现UDP协议的编程.
服务器端:
udpserver.h
#ifndef UDPSERVER_H
#define UDPSERVER_H
#include
#include
#include
#include
#include
#include
#include
namespace Ui {
class UdpServer;
}
class UdpServer : public QDialog
{
Q_OBJECT
public:
explicit UdpServer(QWidget *parent = ,Qt::WindowFlags f=);
~UdpServer();
public slots:
void StartBtnClicked();
void timeout();
private:
int port;
bool isStarted;
QUdpSocket *udpSocket;
QTimer *timer;
private:
QLabel *TimerLabel;
QLineEdit *TextLineEdit;
QPushButton *StartBtn;
QVBoxLayout *mainLayout;
private:
Ui::UdpServer *ui;
};
#endif // UDPSERVER_H
udpserver.cpp
#include "udpserver.h"
#include "ui_udpserver.h"
#include
UdpServer::UdpServer(QWidget *parent,Qt::WindowFlags f) :
QDialog(parent,f),
ui(new Ui::UdpServer)
{
ui->setupUi(this);
setWindowTitle(tr("UDP 服务器"));
TimerLabel = new QLabel(tr("计时器:"),this);
TextLineEdit = new QLineEdit(this);
StartBtn = new QPushButton(tr("开始"),this);
//设置垂直布局
mainLayout = new QVBoxLayout(this);
mainLayout->addWidget(TimerLabel);
mainLayout->addWidget(TextLineEdit);
mainLayout->addWidget(StartBtn);
connect(StartBtn,SIGNAL(clicked(bool)),this,SLOT(StartBtnClicked()));
//设置UDP的端口号参数,服务器定时向此端口发送广播消息
port = ;
isStarted = false;
udpSocket = new QUdpSocket(this);
//创建定时器
timer = new QTimer(this);
//定时发送广播消息
connect(timer,SIGNAL(timeout()),this,SLOT(timeout()));
}
UdpServer::~UdpServer()
{
delete ui;
}
void UdpServer::StartBtnClicked()
{
//打开
if(!isStarted)
{
StartBtn->setText(tr("停止"));
//每隔1000秒发送一个消息
timer->start();
isStarted=true;
}
else
{
StartBtn->setText(tr("开始"));
isStarted = false;
timer->stop();
}
}
void UdpServer::timeout()
{
QString msg = TextLineEdit->text();
int length=;
if(msg=="")
{
return;
}
//QHostAddress::Broadcast 指定向广播地址发送
if(length=udpSocket->writeDatagram(msg.toLatin1(),
msg.length(),QHostAddress::Broadcast,port)!=msg.length())
{
return;
}
}
udpclient.h
#ifndef UDPCLIENT_H
#define UDPCLIENT_H
#include
#include
#include
#include
#include
namespace Ui {
class UdpClient;
}
class UdpClient : public QDialog
{
Q_OBJECT
public:
explicit UdpClient(QWidget *parent = );
~UdpClient();
public slots:
void CloseBtnClicked();
void dataReceived();
private:
int port;
QUdpSocket *udpSocket;
private:
Ui::UdpClient *ui;
QTextEdit *ReceiveTextEdit;
QPushButton *closeBtn;
QVBoxLayout *mainLayout;
};
#endif // UDPCLIENT_H
udpclient.cpp
#include "udpclient.h"
#include "ui_udpclient.h"
#include
#include
UdpClient::UdpClient(QWidget *parent) :
QDialog(parent),
ui(new Ui::UdpClient)
{
ui->setupUi(this);
setWindowTitle(tr("UDP 客户端"));
ReceiveTextEdit = new QTextEdit(this);
closeBtn = new QPushButton(tr("关闭"),this);
mainLayout = new QVBoxLayout(this);
mainLayout->addWidget(ReceiveTextEdit);
mainLayout->addWidget(closeBtn);
connect(closeBtn,SIGNAL(clicked(bool)),this,SLOT(CloseBtnClicked()));
//设置UDP的端口号参数,指定在此端口上监听数据
port = ;
//创建一个QUdpSocket
udpSocket = new QUdpSocket(this);
//连接QIODevice的readyRead()信号
//QUdpSocket也是一个I/O设备,从QIODevice继承而来,当有数据到达I/O设备时,发出readyRead()信号
connect(udpSocket,SIGNAL(readyRead()),this,SLOT(dataReceived()));
//绑定到指定的端口上
bool result=udpSocket->bind(port);
if(!result)
{
QMessageBox::information(this,tr("error"),tr("udp socket create error!"));
return;
}
}
UdpClient::~UdpClient()
{
delete ui;
}
void UdpClient::CloseBtnClicked()
{
close();
}
void UdpClient::dataReceived()
{
//判断UdpSocket中是否有数据报可读
//hasPendingDatagrams()方法在至少有一个数据报可读时返回true
while(udpSocket->hasPendingDatagrams())
{
//实现读取第一个数据报
//pendingDataSize()可以获得第一个数据报的长度
QByteArray datagram;
datagram.resize(udpSocket->pendingDatagramSize());
udpSocket->readDatagram(datagram.data(),datagram.size());
QString msg = datagram.data();
//显示数据内容
ReceiveTextEdit->insertPlainText(msg);
}
}
3 基于TCP的网络聊天室程序
TCP协议能为应用程序提供可靠的通信连接,使一台计算机发出的字节流无差错地送达网络上的其他计算机.因此,对可靠性要求高的数据通信系统往往使用TCP协议传输数据,但在正则收发数据前通信双方必须首先建立连接.
首先启动服务器,一段时间后启动客户端,它与此服务器经过三次握手后建立连接.此后的一段时间内,客户端向服务器发送一个请求,服务器处理这个请求,并为客户端发回一个响应.这个过程一直持续下去,知道客户端为服务器发一个文件结束符,并关闭客户端连接,接着服务器也关闭服务器的连接,结束运行或等待一个新的客户端连接.
Qt中通过QTcpSocket类实现TCP协议的编程.
代码示例:
服务器端
tcpserver.h
#ifndef TCPSERVER_H
#define TCPSERVER_H
#include
#include
#include
#include
#include
#include
#include "serverh.h"
namespace Ui {
class TcpServer;
}
class TcpServer : public QDialog
{
Q_OBJECT
public:
explicit TcpServer(QWidget *parent = );
~TcpServer();
private:
Ui::TcpServer *ui;
QListWidget *ContentListWidget;
QLabel *PortLabe;
QLineEdit *PortLineEdit;
QPushButton *CreateBtn;
QGridLayout *mainLayout;
private:
int port;
serverh *server;
public slots:
void slotCreateServer();
void updateServer(QString,int);
};
#endif // TCPSERVER_H
tcpserver.cpp
#include "tcpserver.h"
#include "ui_tcpserver.h"
TcpServer::TcpServer(QWidget *parent) :
QDialog(parent),
ui(new Ui::TcpServer)
{
ui->setupUi(this);
setWindowTitle(tr("TCP Server"));
ContentListWidget = new QListWidget;
PortLabe = new QLabel(tr("端口: "));
PortLineEdit = new QLineEdit();
CreateBtn = new QPushButton(tr("创建聊天室"));
mainLayout=new QGridLayout(this);
mainLayout->addWidget(ContentListWidget,,,,);
mainLayout->addWidget(PortLabe,,);
mainLayout->addWidget(PortLineEdit,,);
mainLayout->addWidget(CreateBtn,,,,);
port=;
PortLineEdit->setText(QString::number(port));
connect(CreateBtn,SIGNAL(clicked(bool)),this,SLOT(slotCreateServer()));
}
TcpServer::~TcpServer()
{
delete ui;
}
void TcpServer::slotCreateServer()
{
//创建一个serverh对象
server = new serverh(this,port);
//将serverh对象的updateServer()信号与相应的槽函数进行连接
connect(server,SIGNAL(updateServer(QString,int)),this,SLOT(updateServer(QString,int)));
CreateBtn->setEnabled(false);
}
void TcpServer::updateServer(QString msg , int length)
{
ContentListWidget->addItem(msg.left(length));
}
server.h
#ifndef SERVERH_H
#define SERVERH_H
#include
#include
#include "tcpclientsocket.h"//包含TCP的套接字
class serverh : public QTcpServer
{
Q_OBJECT
public:
serverh(QObject *parent=,int port=);
//用来保存与每一个客户端连接的TcpClientSocket
QList
signals:
void updateServer(QString,int);
public slots:
void updateClients(QString,int);
void slotDisconnected(int);
protected:
void incomingConnection(int socketDescriptor);
};
#endif // SERVERH_H
server.cpp
#include "serverh.h"
serverh::serverh(QObject *parent,int port):QTcpServer(parent)
{
//在指定的端口对任意地址进行监听
//QHostAddress定义了几种特殊的IP地址
//QHostAddress定义了几种特殊的IP地址,QHostAddress::Null表示一个空的地址
//QHostAddress::LocalHost表示IPV4的本机地址127.0.0.1
//QHostAddress::LocalHostIPV6表示IPv6的本机地址
//QHostAddress::Broadcast表示广播地址255.255.255.255
//QHostAddress::Any表示Ipv4的任意地址0.0.0.0
//QHostAddress::AnyIPv6表示IPv6的任意地址
listen(QHostAddress::Any,port);
}
//当出现一个新的连接时,QTcpServer触发incomingConnection()函数,参数
//socketDescriptor指定连接的Socket描述符
void serverh::incomingConnection(int socketDescriptor)
{
qDebug() << "receive connect" << endl;
//创建一个新的TcpClientSocket客户端通信
tcpclientsocket *tcpClientSocket = new tcpclientsocket(this);
//连接TcpClientSocket的updateClients信号
connect(tcpClientSocket,SIGNAL(updateClients(QString,int)),this,
SLOT(updateClients(QString,int)));
//连接TcpClientSocket的disconnect信号
connect(tcpClientSocket,SIGNAL(disconnected(int)),this,
SLOT(slotDisconnected(int)));
//将tcpClient加入客户端套接字列表以便管理
tcpClientSocket->setSocketDescriptor(socketDescriptor);
tcpClientSocketList.append(tcpClientSocket);
}
void serverh::updateClients(QString msg, int length)
{
//发出updateServer信号,来通知服务器对话框更新相应的显示状态
qDebug() << msg << endl;
emit updateServer(msg,length);
qDebug() << msg << endl;
for(int i=;i
{
continue;
}
}
}
void serverh::slotDisconnected(int descriptor)
{
for(int i=;i<tcpClientSocketList.count();i++)
{
QTcpSocket *item = tcpClientSocketList.at(i);
if(item->socketDescriptor()==descriptor)
{
tcpClientSocketList.removeAt(i);
return;
}
}
return;
}
tcpclientsocket.h
#ifndef TCPCLIENTSOCKET_H
#define TCPCLIENTSOCKET_H
#include
#include
class tcpclientsocket : public QTcpSocket
{
Q_OBJECT //添加宏是为了实现信号和槽的通信
public:
tcpclientsocket(QObject *parent=);
signals:
void updateClients(QString ,int);
void disconnected(int);
protected slots:
void dataReceived();
void slotDisconnected();
};
#endif // TCPCLIENTSOCKET_H
tcpclientsocket.cpp
#include "tcpclientsocket.h"
#include
tcpclientsocket::tcpclientsocket(QObject *parent)
{
//指定信号与槽的连接关系
//readyRead()是QIODevice的signal,由QTcpSocket继承而来.QIODevice
//是所有输入/输出设备的一个抽象类,其中定义了基本的接口,在Qt中,QTcpSocket也被
//看做一个QIODevice,readyRead()信号在有数据到来时发出
connect(this,SIGNAL(readyRead()),this,SLOT(dataReceived()));
//信号在断开连接时发出
connect(this,SIGNAL(disconnected()),this,SLOT(slotDisconnected()));
}
//当有数据到来的时候触发dataReceived()函数,从套接字中将有效数据取出,然后
//发出updateClients()信号.
//updateClients()信号是通知服务器向聊天室内的所有成员广播信息
void tcpclientsocket::dataReceived()
{
qDebug() << "accept message" << endl;
while(bytesAvailable()>)
{
int length = bytesAvailable();
char buf[];
read(buf,length);
qDebug() << buf << endl;
QString msg=buf;
qDebug() << msg << endl;
emit updateClients(msg,length);
}
}
//槽函数slotDisconnected
void tcpclientsocket::slotDisconnected()
{
emit disconnected(this->socketDescriptor());
}
客户端
tcpclient.h
#ifndef TCPCLIENT_H
#define TCPCLIENT_H
#include
namespace Ui {
class TcpClient;
}
#include
#include
#include
#include
#include
#include
#include
#include
class TcpClient : public QDialog
{
Q_OBJECT
public:
explicit TcpClient(QWidget *parent = );
~TcpClient();
private:
Ui::TcpClient *ui;
QListWidget *contentListWidget;
QLineEdit *sendLineEdit;
QPushButton *sendBtn;
QLabel *userNameLabel;
QLineEdit *userNameLineEdit;
QLabel *serverIPLabel;
QLineEdit *serverIPLineEdit;
QLabel *portLabel;
QLineEdit *portLineEdit;
QPushButton *enterBtn;
QGridLayout *mainLayout;
private:
bool status;
int port;
QHostAddress *serverIP;
QString userName;
QTcpSocket *tcpSocket;
private slots:
void slotEnter();
void slotConnected();
void slotDisconnected();
void dataReceived();
void slotSend();
};
#endif // TCPCLIENT_H
tcpclient.cpp
#include "tcpclient.h"
#include "ui_tcpclient.h"
#include
#include
TcpClient::TcpClient(QWidget *parent) :
QDialog(parent),
ui(new Ui::TcpClient)
{
ui->setupUi(this);
setWindowTitle(tr("TCP Client"));
contentListWidget = new QListWidget;
sendLineEdit = new QLineEdit;
sendBtn = new QPushButton(tr("发送"));
userNameLabel=new QLabel(tr("用户名:"));
userNameLineEdit = new QLineEdit;
serverIPLabel = new QLabel(tr("服务器地址: "));
serverIPLineEdit = new QLineEdit;
portLabel = new QLabel(tr("端口: "));
portLineEdit = new QLineEdit;
enterBtn = new QPushButton(tr("进入聊天室"));
mainLayout = new QGridLayout(this);
mainLayout->addWidget(contentListWidget,,,,);
mainLayout->addWidget(sendLineEdit,,);
mainLayout->addWidget(sendBtn,,);
mainLayout->addWidget(userNameLabel,,);
mainLayout->addWidget(userNameLineEdit,,);
mainLayout->addWidget(serverIPLabel,,);
mainLayout->addWidget(serverIPLineEdit,,);
mainLayout->addWidget(portLabel,,);
mainLayout->addWidget(portLineEdit,,);
mainLayout->addWidget(enterBtn,,,,);
status = false;
port = ;
portLineEdit->setText(QString::number(port));
serverIP=new QHostAddress();
connect(enterBtn,SIGNAL(clicked(bool)),this,SLOT(slotEnter()));
connect(sendBtn,SIGNAL(clicked(bool)),this,SLOT(slotSend()));
sendBtn->setEnabled(false);
}
TcpClient::~TcpClient()
{
delete ui;
}
void TcpClient::slotEnter()
{
//status表示当前的状态,true表示已经进入聊天室,false表示已经离开聊天室
//这里根据status的状态决定是进入还是离开操作
if(!status)
{
//完成输入合法性检验
QString ip = serverIPLineEdit->text();
//用来判断给定的IP地址是否能够被正确解析
if(!serverIP->setAddress(ip))
{
QMessageBox::information(this,tr("error"),tr("server ip address error!"));
return;
}
if(userNameLineEdit->text()=="")
{
QMessageBox::information(this,tr("error"),tr("User name error!"));
return;
} userName = userNameLineEdit->text();
//创建QTcpSocket类对象,并将信号/槽连接起来
tcpSocket = new QTcpSocket(this);
connect(tcpSocket,SIGNAL(connected()),this,SLOT(slotConnected()));
connect(tcpSocket,SIGNAL(disconnected()),this,SLOT(slotDisconnected()));
connect(tcpSocket,SIGNAL(readyRead()),this,SLOT(dataReceived()));
//与TCP服务器端连接,连接成功后发出connected
tcpSocket->connectToHost(\*serverIP,port);
status = true;
}
else
{
int length = ;
//构建一条离开聊天室的消息
QString msg = userName + tr(":Leave Chat Room");
//通知服务器端以上构造的消息
if( ( length=tcpSocket->write( msg.toLatin1(),msg.length() ) )!=msg.length())
{
return;
} //与服务器端口连接,断开后发出disconnected()信号
tcpSocket->disconnectFromHost();
//将status状态复位
status = false;
}
}
//当服务器连上成功后,客户端构造一条进入聊天室的消息,并通知服务器
void TcpClient::slotConnected()
{
qDebug() << "进入服务器" << endl;
sendBtn->setEnabled(true);
enterBtn->setText(tr("离开"));
int length=;
QString msg = userName+tr("Enter Chat Room");
if((length=tcpSocket->write(msg.toLatin1(),msg.length()))!=msg.length())
{
qDebug() << "发送失败" << endl;
return;
}
else
{
qDebug() << "发送成功" << endl;
}
}
void TcpClient::slotDisconnected()
{
sendBtn->setEnabled(false);
enterBtn->setText(tr("进入聊天室"));
}
//当有数据到来时触发此函数,从套接字中将有效数据提出并显示
void TcpClient::dataReceived()
{
while(tcpSocket->bytesAvailable()>)
{
QByteArray datagram;
datagram.resize(tcpSocket->bytesAvailable());
tcpSocket->read(datagram.data(),datagram.size()); QString msg = datagram.data();
contentListWidget->addItem(msg.left(datagram.size()));
}
}
void TcpClient::slotSend()
{
if(sendLineEdit->text()=="")
{
return;
}
QString msg=userName+":"+sendLineEdit->text();
tcpSocket->write(msg.toLatin1(),msg.length());
sendLineEdit->clear();
}
main.cpp
#include "tcpclient.h"
#include
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
TcpClient w;
w.show();
return a.exec();
}
4 网页浏览实例
首先创建一个QNetworkAccessManager类的实例,它用来发送网络请求和接收应答.然后关联了管理器的finished信号和自定义的槽,每当网络应答结束时都会发射这个信号.最后使用了get函数来发送一个网络请求,网络请求使用QNetwrokRequest类表示,get()函数返回一个QNetworkReply对象
mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include
#include
#include
class QNetworkAccessManager;
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = );
~MainWindow();
private slots:
void replyFinished(QNetworkReply *);
private:
Ui::MainWindow *ui;
QNetworkAccessManager \*manager;
};
#endif // MAINWINDOW_H
mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
//创建QNetworkAccessManager类的实例,它用来发送网络请求和接收应答.然后
//管理了管理器的finished()信号和自定义的槽,每当网络应答结束时都会发射
//这个信号.最后使用了get()函数来发送一个网络请求,网络请求使用QNetworkRequest
//类表示,get()函数返回一个QNetworkReply对象
manager = new QNetworkAccessManager(this);
connect(manager,SIGNAL(finished(QNetworkReply\*)),this,
SLOT(replyFinished(QNetworkReply\*)));
manager->get(QNetworkRequest(QUrl("http://www.baidu.com")));
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::replyFinished(QNetworkReply *reply)
{
QString all = reply->readAll();
ui->textBrowser->setText(all);
reply->deleteLater();
}
main.cpp
#include "mainwindow.h"
#include
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}
mianwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include
#include
#include
class QNetworkAccessManager;
#include
class QFile;
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = );
~MainWindow();
void startRequest(QUrl url);
private slots:
void replyFinished(QNetworkReply *);
void httpFinished();
void httpReadyRead();
void updateDataReadProgress(qint64,qint64);
void on\_pushButton\_clicked();
private:
Ui::MainWindow *ui;
QNetworkAccessManager \*manager;
QNetworkReply \*reply;
QUrl url;
QFile \*file;
};
#endif // MAINWINDOW_H
mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
//创建QNetworkAccessManager类的实例,它用来发送网络请求和接收应答.然后
//管理了管理器的finished()信号和自定义的槽,每当网络应答结束时都会发射
//这个信号.最后使用了get()函数来发送一个网络请求,网络请求使用QNetworkRequest
//类表示,get()函数返回一个QNetworkReply对象
manager = new QNetworkAccessManager(this);
connect(manager,SIGNAL(finished(QNetworkReply\*)),this,
SLOT(replyFinished(QNetworkReply\*)));
// manager->get(QNetworkRequest(QUrl("http://www.baidu.com")));
//ui->progressBar->hide();
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::startRequest(QUrl url)
{
//使用get()函数发送网络请求
reply = manager->get(QNetworkRequest(url));
//readyRead()信号继承自QIODevice类,每当有新的数据可以读取时,都会发射该信号
connect(reply,SIGNAL(readyRead()),this,SLOT(httpReadyRead()));
//每当网络请求的下载进度更新时都会发射downloadProgress()信号,用于更新进度条;
connect(reply,SIGNAL(downloadProgress(qint64,qint64)),this,
SLOT(updateDataReadProgress(qint64,qint64)));
//每当应答处理结束时,都会发射finished()信号
connect(reply,SIGNAL(finished()),this,SLOT(httpFinished()));
}
void MainWindow::replyFinished(QNetworkReply *reply)
{
QString all = reply->readAll();
ui->textBrowser->setText(all);
reply->deleteLater();
}
//完成下载后,重新隐藏进度条,删除reply和file对象
void MainWindow::httpFinished()
{
ui->progressBar->hide();
file->flush();
file->close();
reply->deleteLater();
reply = ;
delete file;
file = ;
}
//首先判断是否创建了文件,如果是,则读取返回的所有数据,然后写入文件中.
//该文件示后面的下载按钮单机信号槽中创建并打开的
void MainWindow::httpReadyRead()
{
if(file)
{
file->write(reply->readAll());
}
}
//设置进度条的最大值和当前值
void MainWindow::updateDataReadProgress(qint64 bytesRead, qint64 totalBytes)
{
ui->progressBar->setMaximum(totalBytes);
ui->progressBar->setValue(bytesRead);
}
//使用要下载的文件名创建了本地文件,使用输入的url进行网络请求,并显示进度条
void MainWindow::on_pushButton_clicked()
{
url = ui->lineEdit->text();
QFileInfo info(url.path());
QString fileName(info.fileName());
qDebug() << fileName<<endl;
file = new QFile(fileName);
if(!file->open(QIODevice::WriteOnly))
{
qDebug()<<"file open error";
delete file;
file = ;
return;
}
startRequest(url);
ui->progressBar->setValue();
ui->progressBar->show();
}
手机扫一扫
移动阅读更方便
你可能感兴趣的文章