Qt实现基于多线程的文件传输(服务端,客户端) 您所在的位置:网站首页 电动车锂电池安装视频教程 Qt实现基于多线程的文件传输(服务端,客户端)

Qt实现基于多线程的文件传输(服务端,客户端)

#Qt实现基于多线程的文件传输(服务端,客户端)| 来源: 网络整理| 查看: 265

1. 效果

先看看效果图

这是传输文件完成的界面 客户端 服务端 2. 知识准备

其实文件传输和聊天室十分相似,只不过一个传输的是文字,一个传输的是文件,而这方面的知识,我已经在前面的博客写过了,不了解的同学可以去看一下

C++网络编程 Qt实现网络聊天室(客户端,服务端)

还有多线程相关的知识

Qt中的多线程与线程池浅析+实例 2.1 关于多线程

这次是用多线程实现的文件传输系统,其中对客户端来说,子线程负责连接服务器,发送文件,主线程负责修改进度条,对服务端来说,也是用子线程来处理客户端的请求

2.2 关于文件传输

文件传输采用的是,对客户端,首先是发送出整个文件的大小,需要用到QFileInfo这个类,然后再发送文件

对服务端,先接收文件的大小,然后判断,当接收的文件大小等于第一次接收的文件大小时,停止接收,断开连接

3. 源代码

我在代码里面都有非常详细的注释,所以就直接放上代码啦

3.1 客户端

头文件 mainwindow.h

#ifndef MAINWINDOW_H #define MAINWINDOW_H #include QT_BEGIN_NAMESPACE namespace Ui { class MainWindow; } QT_END_NAMESPACE class MainWindow : public QMainWindow { Q_OBJECT public: MainWindow(QWidget *parent = nullptr); ~MainWindow(); signals: void startConnect(unsigned short,QString); // 发送文件信号 void sendFile(QString path); private slots: void on_connectServer_clicked(); void on_selFile_clicked(); void on_sendFile_clicked(); private: Ui::MainWindow *ui; }; #endif // MAINWINDOW_H

源文件 mainwindow.cpp

#include "mainwindow.h" #include "ui_mainwindow.h" #include #include #include "sendfile.h" #include MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) , ui(new Ui::MainWindow) { ui->setupUi(this); // 设置IP和端口 ui->ip->setText("127.0.0.1"); ui->port->setText("8989"); // 设置进度条 ui->progressBar->setRange(0,100); ui->progressBar->setValue(0); // 客户端在子线程中连接服务器 // 创建线程对象 QThread* t = new QThread; // 创建任务对象 SendFile* worker = new SendFile; // 将worker移动到子线程t中 worker->moveToThread(t); // 当发送sendFile信号,让worker的sendFile函数处理(子线程) connect(this,&MainWindow::sendFile,worker,&SendFile::sendFile); // 通过信号,让worker开始工作 // 因为worker 已经移动到了子线程中,因此connectServer这个槽函数是在子线程中执行的 connect(this,&MainWindow::startConnect,worker,&SendFile::connectServer); // 处理子线程发送的信号 // 连接成功 connect(worker,&SendFile::connectOK,this,[=](){ QMessageBox::information(this,"连接服务器","已经成功的连接了服务器,恭喜!"); }); // 断开连接 connect(worker,&SendFile::gameover,this,[=](){ // 资源释放 t->quit(); t->wait(); worker->deleteLater(); t->deleteLater(); }); connect(worker,&SendFile::curPercent,ui->progressBar,&QProgressBar::setValue); // 启动线程 t->start(); } MainWindow::~MainWindow() { delete ui; } void MainWindow::on_connectServer_clicked() { QString ip = ui->ip->text(); unsigned short port = ui->port->text().toUShort(); emit startConnect(port,ip); } void MainWindow::on_selFile_clicked() { QString path = QFileDialog::getSaveFileName(); // 判断路径是否为空 if(path.isEmpty()) { QMessageBox::warning(this,"打开文件","选择的文件路径不能为空"); return; } ui->filePath->setText(path); } void MainWindow::on_sendFile_clicked() { // 发送文件信号 emit sendFile(ui->filePath->text()); }

头文件 Send File.h

#ifndef SENDFILE_H #define SENDFILE_H #include #include class SendFile : public QObject { Q_OBJECT public: explicit SendFile(QObject *parent = nullptr); // 连接服务器 void connectServer(unsigned short port,QString ip); // 发送文件 void sendFile(QString path); signals: // 通知主线程连接成功 void connectOK(); // 通知主线程连接成功 void gameover(); // 通知主线程发送文件进度百分比 void curPercent(int num); private: QTcpSocket* m_tcp; }; #endif // SENDFILE_H

源文件SendFile.cpp

#include "sendfile.h" #include #include #include SendFile::SendFile(QObject* parent) : QObject(parent) { } void SendFile::connectServer(unsigned short port, QString ip) { m_tcp = new QTcpSocket; m_tcp->connectToHost(QHostAddress(ip),port); // 通知主线程连接成功 connect(m_tcp,&QTcpSocket::connected,this,&SendFile::connectOK); // 通知主线程断开连接 connect(m_tcp,&QTcpSocket::disconnected,this,[=](){ // 断开连接,释放资源 m_tcp->close(); m_tcp->deleteLater(); emit gameover(); }); } void SendFile::sendFile(QString path) { QFile file(path); // 获取文件信息 QFileInfo info(path); int fileSize = info.size(); file.open(QFile::ReadOnly); // 一行一行的读文件 while(!file.atEnd()){ static int num = 0; // 为了让服务器端知道什么时候停止接收,所以得发送文件的大小 if(num ==0){ m_tcp->write((char*)&fileSize,4); } QByteArray line = file.readLine(); // 计算百分比,发给主线程 num +=line.size(); int percent =(num*100/fileSize); emit curPercent(percent); m_tcp->write(line); } } 3.2 服务端

头文件mainwindow.h

#ifndef MAINWINDOW_H #define MAINWINDOW_H #include #include QT_BEGIN_NAMESPACE namespace Ui { class MainWindow; } QT_END_NAMESPACE class MainWindow : public QMainWindow { Q_OBJECT public: MainWindow(QWidget *parent = nullptr); ~MainWindow(); private slots: void on_setListen_clicked(); private: Ui::MainWindow *ui; QTcpServer* m_s; }; #endif // MAINWINDOW_H

源文件maindow.cpp

#include "mainwindow.h" #include "ui_mainwindow.h" #include #include #include "recvfile.h" MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) , ui(new Ui::MainWindow) { ui->setupUi(this); m_s = new QTcpServer(this); connect(m_s,&QTcpServer::newConnection,this,[=](){ QTcpSocket* tcp = m_s->nextPendingConnection(); // 创建子线程,tcp通过参数传递 RecvFile* subThread = new RecvFile(tcp); subThread->start(); connect(subThread,&RecvFile::over,this,[=](){ subThread->exit(); subThread->wait(); subThread->deleteLater(); QMessageBox::information(this,"文件接受","文件接收完毕!!!"); }); }); } MainWindow::~MainWindow() { delete ui; } void MainWindow::on_setListen_clicked() { unsigned short port = ui->port->text().toUShort(); m_s->listen(QHostAddress::Any,port); }

头文件recvfile.h

#ifndef RECVFILE_H #define RECVFILE_H #include #include class RecvFile : public QThread { Q_OBJECT public: explicit RecvFile(QTcpSocket* tcp,QObject *parent = nullptr); protected: void run() override; private: QTcpSocket* m_tcp; signals: void over(); }; #endif // RECVFILE_H

源文件recvfile.cpp

#include "recvfile.h" #include RecvFile::RecvFile(QTcpSocket* tcp,QObject *parent) : QThread(parent) { m_tcp = tcp; } void RecvFile::run() { QFile* file = new QFile("recv.txt"); file->open(QFile::WriteOnly); // 接收数据 connect(m_tcp,&QTcpSocket::readyRead,this,[=](){ static int count = 0; static int total = 0; if(count == 0){ m_tcp->read((char*)&total,4); } // 读出剩余数据 QByteArray all = m_tcp->readAll(); count += all.size(); file->write(all); if(count == total){ m_tcp->close(); m_tcp->deleteLater(); file->close(); file->deleteLater(); emit over(); } }); // 进入事件循环 exec(); } 3.4 文件目录 4. 结束语

如果有些小伙伴需要工程文件等,可以联系我

原文地址:https://www.cnblogs.com/wanghongyang/p/14926303.html



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有