在QT实现文件传输
来源:互联网 发布:网络管理视频教程下载 编辑:程序博客网 时间:2024/06/13 06:12
过程如下:
1、服务器端设置监听套接字,开始监听;
2、客户端在连接成功时开始传送文件,有connected()信号连接send()槽,send()发送文件头信息,包括文件名、文件总大小和文件名大小等;
3、传送完文件头信息时开始传送文件内容,有bytesWritten(qint64)信号连接到goOnSend(qint64)槽,前者是当想套接字写入数据时会出发的信号,即当已经想套接字写入数据,就继续传送数据,有send()传送文件头信息开始触发,直到文件传完为止。
4、在服务器端,首先接收文件头信息,然后读取文件名来用新建文件的方式打开一个文件,然后读取文件名即文件等大小信息,用来更新进度条和继续接收数据;
5、实现循环传输,在客户端,因为第一次send()是由connected()信号触发的,之后的每次传送应该手动调用send();在服务器端,在有新数据到达时,会判断是否为头文件,因此在每次文件传完的时候将byteReceived重置为0,即下一次再接收到数据的时候依据byteReceived判断的结果就是一个新文件了。
客户端代码:
- #ifndef WIDGET_H
- #define WIDGET_H
-
- #include <QWidget>
- #include <QTcpSocket>
- #include <QFile>
- #include <string>
-
- namespace Ui {
- class Widget;
- }
-
- class Widget : public QWidget
- {
- Q_OBJECT
-
- public:
- explicit Widget(QWidget *parent = 0);
- ~Widget();
-
- private:
- Ui::Widget *ui;
-
- QTcpSocket *tcpClient;
- QFile *localFile;
- QString fileName;
-
- QByteArray outBlock;
- qint64 loadSize;
- qint64 byteToWrite;
- qint64 totalSize;
-
- int sendTimes;
-
- private slots:
- void send();
- void goOnSend(qint64);
- void on_openPushButton_clicked();
- void on_sendPushButton_clicked();
- };
-
- #endif // WIDGET_H
widget.cpp
- #include "widget.h"
- #include "ui_widget.h"
- #include <QHostAddress>
- #include <QTextCodec>
- #include <QFileDialog>
-
- Widget::Widget(QWidget *parent) :
- QWidget(parent),
- ui(new Ui::Widget)
- {
- ui->setupUi(this);
-
- ui->progressLabel->hide();
- QTextCodec::setCodecForLocale(QTextCodec::codecForName("UTF8"));
-
- tcpClient = new QTcpSocket(this);
- sendTimes = 0;
-
- connect(tcpClient, SIGNAL(connected()), this, SLOT(send()));
- connect(tcpClient, SIGNAL(bytesWritten(qint64)), this, SLOT(goOnSend(qint64)));
- }
-
- void Widget::send()
- {
- byteToWrite = localFile->size();
- totalSize = localFile->size();
-
- loadSize = 4*1024;
-
- QDataStream out(&outBlock, QIODevice::WriteOnly);
- QString currentFileName = fileName.right(fileName.size() - fileName.lastIndexOf('/')-1);
-
- out<<qint64(0)<<qint64(0)<<currentFileName;
-
- totalSize += outBlock.size();
- byteToWrite += outBlock.size();
-
- out.device()->seek(0);
- out<<totalSize<<qint64(outBlock.size());
-
- tcpClient->write(outBlock);
-
- ui->progressLabel->show();
- ui->sendProgressBar->setMaximum(totalSize);
- ui->sendProgressBar->setValue(totalSize - byteToWrite);
- }
-
- void Widget::goOnSend(qint64 numBytes)
- {
- byteToWrite -= numBytes;
- outBlock = localFile->read(qMin(byteToWrite, loadSize));
- tcpClient->write(outBlock);
-
- ui->sendProgressBar->setMaximum(totalSize);
- ui->sendProgressBar->setValue(totalSize - byteToWrite);
-
- if(byteToWrite == 0)
- ui->sendStatusLabel->setText(tr("文件发送完毕!"));
- }
-
- Widget::~Widget()
- {
- delete ui;
- }
-
- void Widget::on_openPushButton_clicked()
- {
- ui->sendStatusLabel->setText(tr("正在打开文件..."));
- ui->sendProgressBar->setValue(0);
-
- loadSize = 0;
- byteToWrite = 0;
- totalSize = 0;
- outBlock.clear();
-
- fileName = QFileDialog::getOpenFileName(this);
- localFile = new QFile(fileName);
- localFile->open(QFile::ReadOnly);
-
- ui->sendStatusLabel->setText(tr("已打开文件 %1").arg(fileName));
- }
-
- void Widget::on_sendPushButton_clicked()
- {
- if(sendTimes == 0)
- {
- tcpClient->connectToHost(QHostAddress("192.168.1.137"), 1000);
- sendTimes = 1;
- }
- else
- send();
-
- ui->sendStatusLabel->setText(tr("正在发送文件 %1").arg(fileName));
- }
服务端代码:
widget.h
- #ifndef WIDGET_H
- #define WIDGET_H
-
- #include <QWidget>
- #include <QtNetwork/QTcpServer>
- #include <QtNetwork/QTcpSocket>
- #include <QFile>
- #include <QString>
-
- namespace Ui {
- class Widget;
- }
-
- class Widget : public QWidget
- {
- Q_OBJECT
-
- public:
- explicit Widget(QWidget *parent = 0);
- ~Widget();
-
- private:
- Ui::Widget *ui;
-
- QTcpServer *server;
- QTcpSocket *receivedSocket;
- QFile *newFile;
-
- QByteArray inBlock;
- QString fileName;
- qint64 totalSize;
- qint64 byteReceived;
-
- private slots:
- void acceptConnection();
- void readClient();
- void on_pushButton_clicked();
- };
-
- #endif // WIDGET_H
widget.cpp
- #include "widget.h"
- #include "ui_widget.h"
- #include <QTextCodec>
-
- Widget::Widget(QWidget *parent) :
- QWidget(parent),
- ui(new Ui::Widget)
- {
- ui->setupUi(this);
- ui->progressLabel->hide();
QTextCodec::setCodecForLocale(QTextCodec::codecForName("UTF8"));
- }
-
- void Widget::acceptConnection()
- {
- ui->receivedStatusLabel->setText(tr("已连接,正在准备接收文件!"));
-
- receivedSocket = server->nextPendingConnection();
- connect(receivedSocket, SIGNAL(readyRead()), this, SLOT(readClient()));
- }
-
- void Widget::readClient()
- {
- ui->receivedStatusLabel->setText(tr("正在接收文件..."));
-
- if(byteReceived == 0)
- {
- ui->receivedProgressBar->setValue(0);
-
- QDataStream in(receivedSocket);
- in>>totalSize>>byteReceived>>fileName;
- newFile = new QFile(fileName);
- newFile->open(QFile::WriteOnly);
- }
- else
- {
- inBlock = receivedSocket->readAll();
-
- byteReceived += inBlock.size();
- newFile->write(inBlock);
- newFile->flush();
- }
- ui->progressLabel->show();
- ui->receivedProgressBar->setMaximum(totalSize);
- ui->receivedProgressBar->setValue(byteReceived);
-
- if(byteReceived == totalSize)
- {
- ui->receivedStatusLabel->setText(tr("%1接收完成").arg(fileName));
-
- inBlock.clear();
- byteReceived = 0;
- totalSize = 0;
- }
- }
-
- Widget::~Widget()
- {
- delete ui;
- }
- void Widget::on_pushButton_clicked()
- {
- totalSize = 0;
- byteReceived = 0;
-
- server = new QTcpServer(this);
- server->listen(QHostAddress("192.168.1.137"), 1000);
-
- connect(server, SIGNAL(newConnection()), this, SLOT(acceptConnection()));
-
- ui->receivedProgressBar->setValue(0);
- ui->receivedStatusLabel->setText(tr("开始监听..."));
- }