您的位置:首页 > 理论基础 > 计算机网络

Qt TCP文件传输

2016-05-22 19:27 344 查看
FileServer类为TCP服务端提供文件下载,Downloader为TCP客户端,连接到服务端下载文件

fileserver.h

#ifndef FILESERVER_H
#define FILESERVER_H

#include <QObject>
#include<QtNetwork>
class FileServer : public QObject
{
Q_OBJECT
public:
explicit FileServer(QObject *parent = 0);
~FileServer();
void startFileServer(qint16 linstenport=45455);
void setFile(QString filepath);
private:

qint16 tcpPort;
QTcpServer *tcpServer;
QString fileName;
QString theFileName;
QFile *localFile;

qint64 totalBytes;//总共数据大小
qint64 bytesWritten;//已发送数据大小
qint64 bytesToWrite;//还剩数据大小
qint64 loadSize;//缓冲区大小
QByteArray outBlock;//缓存一次发送的数据

QTcpSocket *clientConnection;

QTime time;//计时器

signals:
// void finshTransfer(QString filename);
void updateProgressBar(int value);
public slots:
void sendFile();
void updateClientProgress(qint64 numBytes);
};

#endif // FILESERVER_H


fileserver.cpp
#include "fileserver.h"

FileServer::FileServer(QObject *parent) : QObject(parent)
{
tcpServer = new QTcpServer(this);
connect(tcpServer,SIGNAL(newConnection()),this,SLOT(sendFile()));
}

void FileServer::startFileServer(qint16 linstenport){
tcpPort=linstenport;//监听端口

loadSize = 1024;//缓冲区大小1K
totalBytes = 0;
bytesWritten = 0;
bytesToWrite = 0;

if(!tcpServer->listen(QHostAddress::Any,tcpPort))//开始监听
{
qDebug() << tcpServer->errorString();
tcpServer->close();
return;
}else qDebug() <<"---FileServer---开始监听端口:"<<tcpPort;
}

void FileServer::setFile(QString filepath){
localFile = new QFile(filepath);
theFileName=localFile->fileName();
if(!localFile->open((QFile::ReadOnly))){//以只读方式打开
qDebug() <<"---FileServer---无法读取文件 ";
return;
}
}

void FileServer::sendFile(){
clientConnection = tcpServer->nextPendingConnection();
connect(clientConnection,SIGNAL(bytesWritten(qint64)),SLOT(updateClientProgress(qint64)));
//bytesWritten SIGNAL 与 updateClientProgress SLOT 构成一个事件循环,直到文件发送完毕

qDebug() <<"---FileServer---开始传送文件!";
bytesToWrite=totalBytes = localFile->size();
//文件总大小
outBlock = localFile->read(qMin(bytesToWrite,loadSize));//从文件中读取数据到缓冲区
bytesToWrite = totalBytes - clientConnection->write(outBlock);
bytesWritten+=outBlock.size();
qDebug()<<"---FileServer---已发送:"<<bytesWritten<<" 剩余:"<<bytesToWrite<<" 总共:"<<totalBytes;
//发送完头数据后剩余数据的大小,即文件实际内容的大小
//发送成功后会发射SIGNAL(bytesWritten(qint64))

int sentRate=((float)bytesWritten/totalBytes)*100;
emit updateProgressBar(sentRate);//发射更新进度条信号

outBlock.resize(0);

}
void FileServer::updateClientProgress(qint64 numBytes) //更新进度条,实现文件的传送
{
bytesWritten +=numBytes;
//已经发送数据的大小
if(bytesToWrite > 0) //如果还有数据待发送
{
outBlock = localFile->read(qMin(bytesToWrite,loadSize));//从文件中读取数据
//每次发送loadSize大小的数据,这里设置为4KB,如果剩余的数据不足4KB,
//就发送剩余数据的大小
bytesToWrite -= (int)clientConnection->write(outBlock);
//发送完一次数据后还剩余数据的大小
int sentRate=((float)bytesWritten/totalBytes)*100;
emit updateProgressBar(sentRate);//发射更新进度条信号

outBlock.resize(0);
//清空发送缓冲区
qDebug()<<"---FileServer---已发送:"<<bytesWritten<<" 剩余:"<<bytesToWrite;
}
else//如果数据发送完毕
{
totalBytes = 0;
bytesWritten = 0;
bytesToWrite = 0;
//归零
localFile->close(); //如果没有发送任何数据,则关闭文件
qDebug()<<tr("---FileServer---传送文件 %1 成功").arg(fileName);
clientConnection->close();
// emit finshTransfer(theFileName);

}

}
FileServer::~FileServer(){
delete tcpServer;
}


downloader.h

#ifndef DOWNLOADER_H
#define DOWNLOADER_H

#include <QObject>
#include<QtNetwork>

class Downloader : public QObject
{
Q_OBJECT
public:
explicit Downloader(QObject *parent = 0);
~Downloader();
void download(QString filesavepath, qint64 filesize, QString ipAddress,qint16 Port=45455);
private:
QTcpSocket *tcpClient;
quint16 blockSize;
QHostAddress hostAddress;
qint16 tcpPort;

qint64 TotalBytes;
qint64 bytesReceived;
qint64 bytesToReceive;

qint64 thefileSize;
QString fileName;
QFile *localFile;
QByteArray inBlock;

QTime time;

signals:
void finshDownload(QString filename);
void updateProgressBar(int value);
public slots:
void newConnect();
void readMessage();
void closeConnect();
void displayError(QAbstractSocket::SocketError);

};

#endif // DOWNLOADER_H

downloader.cpp

#include "downloader.h"
#include<QHostAddress>
Downloader::Downloader(QObject *parent) : QObject(parent)
{

tcpClient = new QTcpSocket(this);
tcpPort = 45455;
connect(tcpClient,SIGNAL(readyRead()),this,SLOT(readMessage()));
connect(tcpClient,SIGNAL(disconnected()),this,SLOT(closeConnect()));
connect(tcpClient,SIGNAL(error(QAbstractSocket::SocketError)),this,
SLOT(displayError(QAbstractSocket::SocketError)));
}

void Downloader::download(QString filesavepath,qint64 filesize,QString ipAddress,qint16 Port){
qDebug()<<"----Downloader---文件保存到:"<<filesavepath;
localFile=new QFile(filesavepath);
thefileSize=filesize;

if(!localFile->open(QFile::WriteOnly)){
qDebug()<<"----Downloader---无法读取文件 ";
return;
}
hostAddress = QHostAddress(ipAddress);
tcpPort=Port;
newConnect();
}
void Downloader::newConnect()
{
TotalBytes = 0;
bytesReceived = 0;
blockSize = 0;

tcpClient->abort();
tcpClient->connectToHost(hostAddress,tcpPort);
time.start();
}
void Downloader::readMessage()
{
float useTime = time.elapsed();

bytesReceived += tcpClient->bytesAvailable();
inBlock = tcpClient->readAll();
localFile->write(inBlock);
inBlock.resize(0);

// double speed = bytesReceived / useTime;
int downedRate=((float)bytesReceived/thefileSize)*100;
emit updateProgressBar(downedRate);//发射更新进度条信号
qDebug()<<tr("----Downloader---已接收 %1B(%2\%)用时:%3").arg(bytesReceived)
.arg(downedRate)
.arg((float)useTime/1000);

if(bytesReceived==thefileSize){
qDebug()<<tr("----Downloader---接收完毕");
localFile->close();
tcpClient->close();

emit finshDownload(fileName);//发送完毕信号
}

}
void Downloader::closeConnect(){
qDebug()<<tr("----Downloader---连接关闭");
localFile->close(); //接收完文件后,一定要关闭,不然可能出问题
tcpClient->close();
}

void Downloader::displayError(QAbstractSocket::SocketError socketError) //错误处理
{
switch(socketError)
{
case QAbstractSocket::RemoteHostClosedError : break;
default : qDebug() << tcpClient->errorString();
}
}
Downloader::~Downloader(){
delete tcpClient;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  qt tcp 文件传输