Qt TCP文件传输

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;
}




  • 2
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值