首页 > 其他 > 详细

TCP文件传输-服务端类的实现

时间:2021-03-14 15:23:57      阅读:37      评论:0      收藏:0      [点我收藏+]
#ifndef TCPSERVER_H
#define TCPSERVER_H

#include <QDialog>
#include <QTcpServer>
#include <QFile>
#include <QTime>
#include<QString>

namespace Ui {
class TcpServer;
}

class TcpServer : public QDialog
{
    Q_OBJECT

public:
    explicit TcpServer(QWidget *parent = 0);
    void paintEvent(QPaintEvent *);

    void refused();  //拒绝接收文件函数

    void initServer(); //初始化服务器函数

  signals:
    void sendFileName(QString fileName); //发送文件名信号

protected:
    void closeEvent(QCloseEvent *);



    ~TcpServer();

private slots:
    void on_serverOpenBtn_clicked();

    void on_serverSendBtn_clicked();

    void on_serverCloseBtn_clicked();

    void sendMessage(); //发送数据

    void updateClientProgress(qint64 numBytes); //更新进度条

private:
    Ui::TcpServer *ui;
    QTcpServer *tcpServer; //TCP对象
    qint16 tcpPort; //tcp的端口号
    QString fileName;
    QString theFileName;
    QFile *localFile; //待发送的文件

    qint64 TotalBytes;  //发送数据总大小
    qint64 bytesWritten;  //已发送数据大小
    qint64 bytesToWrite;  //剩余数据大小
    qint64 loadSize;  //每次发送数据的大小
    QByteArray outBlock;//缓存一次发送的数据
    QTcpSocket *clientConnection; //TCP连接套接字
    QTime time;//计时器
};

#endif // TCPSERVER_H
#include "tcpserver.h"
#include "ui_tcpserver.h"
#include<Qpainter>
#include <QTcpSocket>
#include <QFileDialog>
#include <QMessageBox>

//using namespace std::tr1;




TcpServer::TcpServer(QWidget *parent) :
    QDialog(parent),
    ui(new Ui::TcpServer)
{
    ui->setupUi(this);
    this->setFixedSize(500,300);
    tcpServer=new QTcpServer(this);

    tcpPort=6688;
    //connect(TcpServer,&TcpServer::newConnection,this,&TcpServer::sendMessage);

    connect(tcpServer,SIGNAL(newConnection()),this,SLOT(sendMessage())); //当有客服端连接时,触发连接信号,启动发送数据函数
    initServer(); //初始化服务器
}



void TcpServer::closeEvent(QCloseEvent *)
{
    on_serverCloseBtn_clicked();
}

//绘制背景图
void TcpServer::paintEvent(QPaintEvent *)
{

    QPainter painter(this);
    QPixmap pix;
    pix.load(":/res/bluebackground.jpg");
    painter.drawPixmap(0,0,this->width(),this->height(),pix);



}

void TcpServer::refused()
{
       //当对方拒绝接收文件,关闭服务器
        tcpServer->close();
        ui->serverStatusLabel->setText(tr("对方拒绝接收文件"));
}

//服务器初始化
void TcpServer::initServer()
{
    loadSize=64*1024;
    TotalBytes=0;
    bytesWritten=0;
    bytesToWrite=0;
    ui->serverStatusLabel->setText("选择待发送的文件");
    ui->progressBar->reset();
    ui->serverOpenBtn->setEnabled(true);
    ui->serverSendBtn->setEnabled(false);
    tcpServer->close();


}

void TcpServer::updateClientProgress(qint64 numBytes)

{
    qApp->processEvents(); //防止传输文件时,界面冻结
    if(bytesToWrite > 0){
        outBlock = localFile->read(qMin(bytesToWrite,loadSize));  //数据流读入一次传输的文件数据
        bytesToWrite -= (int)clientConnection->write(outBlock);  //套接字写数据流中的缓存,bytesToWrite计算剩余需要发送的数据
        outBlock.resize(0);
    }
    else{
        localFile->close();
    }
    ui->progressBar->setMaximum(TotalBytes);
    ui->progressBar->setValue(bytesWritten);


    float useTime = time.elapsed();  //elapsed获得耗费的时间ms
    double speed = bytesWritten / useTime;
    ui->serverStatusLabel->setText(tr("已发送 %1MB (%2MB/s) \n共%3MB 已用时:%4秒\n估计剩余时间:%5秒")
                                   .arg(bytesWritten / (1024*1024))//已发送
                                   .arg(speed*1000/(1024*1024),0,f,2)//速度,毫秒换成秒
                                   .arg(TotalBytes / (1024 * 1024))//总大小
                                   .arg(useTime/1000,0,f,0)//用时
                                   .arg(TotalBytes/speed/1000 - useTime/1000,0,f,0));//剩余时间

    //判断文件是否全部发送完
    if(bytesWritten == TotalBytes)
        ui->serverStatusLabel->setText(tr("传送文件 %1 成功").arg(theFileName));


}




TcpServer::~TcpServer()
{
    delete ui;
}

void TcpServer::on_serverOpenBtn_clicked()
{
       fileName = QFileDialog::getOpenFileName(this);  //获得文件名(含文件地址信息)
        if(!fileName.isEmpty())
        {
            theFileName = fileName.right(fileName.size() - fileName.lastIndexOf(/)-1); //获取文件地址后的文件名字
            ui->serverStatusLabel->setText(tr("要传送的文件为:%1 ").arg(theFileName));
            ui->serverSendBtn->setEnabled(true);
            ui->serverOpenBtn->setEnabled(false);
        }
}

void TcpServer::on_serverSendBtn_clicked()
{
    if(!tcpServer->listen(QHostAddress::Any,tcpPort))//开始监听,//任意地址
       {
           qDebug() << tcpServer->errorString();
           close();
           return;
       }

       ui->serverStatusLabel->setText(tr("等待对方接收中"));
       emit sendFileName(theFileName);
}

void TcpServer::on_serverCloseBtn_clicked()
{
    //关闭监听,关闭服务器,终止连接和套接字,关闭对话框
    if(tcpServer->isListening())
        {
            tcpServer->close();
            clientConnection->abort();
        }
        this->close();
}

//发送数据文件头结构
void TcpServer::sendMessage()
{
    ui->serverSendBtn->setEnabled(false);
    clientConnection=tcpServer->nextPendingConnection(); //获取连接过来的套接字
    //一旦有已发送的数据信号,就触发更新进度条的函数
    connect(clientConnection,SIGNAL(bytesWritten(qint64)),this,SLOT(updateClientProgress(qint64)));
            ui->serverStatusLabel->setText(tr("开始传送文件 %1 !").arg(theFileName));
    localFile=new QFile(fileName); //创建待发送的文件
    if(!localFile->open((QFile::ReadOnly)))
    {
        QMessageBox::warning(this,tr("提醒"),tr("无法读取文件 %1:\n%2").arg(fileName).arg(localFile->errorString()));
        return;
    }
    TotalBytes = localFile->size(); //文件大小

    QDataStream sendOut(&outBlock,QIODevice::WriteOnly);

    sendOut.setVersion(QDataStream::Qt_4_6);  //设置数据流版本,cs需要相同
    time.start();  //开始计时
    QString currentFile = fileName.right(fileName.size() - fileName.lastIndexOf(/)-1); //返回最后“/”后的字符串,文件名
    sendOut<<qint64(0)<<qint64(0)<<currentFile; //数据大小,文件名大小,文件名
    TotalBytes += outBlock.size(); //总大小=总大小信息+文件名大小信息+文件名+文件大小
    sendOut.device()->seek(0);
    sendOut<<TotalBytes<<qint64((outBlock.size()-sizeof(qint64)*2));
    bytesToWrite = TotalBytes - clientConnection->write(outBlock); //发送文件头结构后的剩余数据大小
    outBlock.resize(0);

}

 

TCP文件传输-服务端类的实现

原文:https://www.cnblogs.com/charles48789982/p/14532490.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!