1. 效果

先看看效果图

  • 这是传输文件完成的界面

  • 客户端

  • 服务端

2. 知识准备

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

还有多线程相关的知识

2.1 关于多线程

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

2.2 关于文件传输

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

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

3. 源代码

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

3.1 客户端

头文件 mainwindow.h

  1. #ifndef MAINWINDOW_H
  2. #define MAINWINDOW_H
  3. #include <QMainWindow>
  4. QT_BEGIN_NAMESPACE
  5. namespace Ui { class MainWindow; }
  6. QT_END_NAMESPACE
  7. class MainWindow : public QMainWindow
  8. {
  9. Q_OBJECT
  10. public:
  11. MainWindow(QWidget *parent = nullptr);
  12. ~MainWindow();
  13. signals:
  14. void startConnect(unsigned short,QString);
  15. // 发送文件信号
  16. void sendFile(QString path);
  17. private slots:
  18. void on_connectServer_clicked();
  19. void on_selFile_clicked();
  20. void on_sendFile_clicked();
  21. private:
  22. Ui::MainWindow *ui;
  23. };
  24. #endif // MAINWINDOW_H

源文件 mainwindow.cpp

  1. #include "mainwindow.h"
  2. #include "ui_mainwindow.h"
  3. #include <QMessageBox>
  4. #include <QThread>
  5. #include "sendfile.h"
  6. #include <QFileDialog>
  7. MainWindow::MainWindow(QWidget *parent)
  8. : QMainWindow(parent)
  9. , ui(new Ui::MainWindow)
  10. {
  11. ui->setupUi(this);
  12. // 设置IP和端口
  13. ui->ip->setText("127.0.0.1");
  14. ui->port->setText("8989");
  15. // 设置进度条
  16. ui->progressBar->setRange(0,100);
  17. ui->progressBar->setValue(0);
  18. // 客户端在子线程中连接服务器
  19. // 创建线程对象
  20. QThread* t = new QThread;
  21. // 创建任务对象
  22. SendFile* worker = new SendFile;
  23. // 将worker移动到子线程t中
  24. worker->moveToThread(t);
  25. // 当发送sendFile信号,让worker的sendFile函数处理(子线程)
  26. connect(this,&MainWindow::sendFile,worker,&SendFile::sendFile);
  27. // 通过信号,让worker开始工作
  28. // 因为worker 已经移动到了子线程中,因此connectServer这个槽函数是在子线程中执行的
  29. connect(this,&MainWindow::startConnect,worker,&SendFile::connectServer);
  30. // 处理子线程发送的信号
  31. // 连接成功
  32. connect(worker,&SendFile::connectOK,this,[=](){
  33. QMessageBox::information(this,"连接服务器","已经成功的连接了服务器,恭喜!");
  34. });
  35. // 断开连接
  36. connect(worker,&SendFile::gameover,this,[=](){
  37. // 资源释放
  38. t->quit();
  39. t->wait();
  40. worker->deleteLater();
  41. t->deleteLater();
  42. });
  43. connect(worker,&SendFile::curPercent,ui->progressBar,&QProgressBar::setValue);
  44. // 启动线程
  45. t->start();
  46. }
  47. MainWindow::~MainWindow()
  48. {
  49. delete ui;
  50. }
  51. void MainWindow::on_connectServer_clicked()
  52. {
  53. QString ip = ui->ip->text();
  54. unsigned short port = ui->port->text().toUShort();
  55. emit startConnect(port,ip);
  56. }
  57. void MainWindow::on_selFile_clicked()
  58. {
  59. QString path = QFileDialog::getSaveFileName();
  60. // 判断路径是否为空
  61. if(path.isEmpty())
  62. {
  63. QMessageBox::warning(this,"打开文件","选择的文件路径不能为空");
  64. return;
  65. }
  66. ui->filePath->setText(path);
  67. }
  68. void MainWindow::on_sendFile_clicked()
  69. {
  70. // 发送文件信号
  71. emit sendFile(ui->filePath->text());
  72. }

头文件 Send File.h

  1. #ifndef SENDFILE_H
  2. #define SENDFILE_H
  3. #include <QObject>
  4. #include <QTcpSocket>
  5. class SendFile : public QObject
  6. {
  7. Q_OBJECT
  8. public:
  9. explicit SendFile(QObject *parent = nullptr);
  10. // 连接服务器
  11. void connectServer(unsigned short port,QString ip);
  12. // 发送文件
  13. void sendFile(QString path);
  14. signals:
  15. // 通知主线程连接成功
  16. void connectOK();
  17. // 通知主线程连接成功
  18. void gameover();
  19. // 通知主线程发送文件进度百分比
  20. void curPercent(int num);
  21. private:
  22. QTcpSocket* m_tcp;
  23. };
  24. #endif // SENDFILE_H

源文件SendFile.cpp

  1. #include "sendfile.h"
  2. #include <QFile>
  3. #include <QHostAddress>
  4. #include <QFileInfo>
  5. SendFile::SendFile(QObject* parent) : QObject(parent)
  6. {
  7. }
  8. void SendFile::connectServer(unsigned short port, QString ip)
  9. {
  10. m_tcp = new QTcpSocket;
  11. m_tcp->connectToHost(QHostAddress(ip),port);
  12. // 通知主线程连接成功
  13. connect(m_tcp,&QTcpSocket::connected,this,&SendFile::connectOK);
  14. // 通知主线程断开连接
  15. connect(m_tcp,&QTcpSocket::disconnected,this,[=](){
  16. // 断开连接,释放资源
  17. m_tcp->close();
  18. m_tcp->deleteLater();
  19. emit gameover();
  20. });
  21. }
  22. void SendFile::sendFile(QString path)
  23. {
  24. QFile file(path);
  25. // 获取文件信息
  26. QFileInfo info(path);
  27. int fileSize = info.size();
  28. file.open(QFile::ReadOnly);
  29. // 一行一行的读文件
  30. while(!file.atEnd()){
  31. static int num = 0;
  32. // 为了让服务器端知道什么时候停止接收,所以得发送文件的大小
  33. if(num ==0){
  34. m_tcp->write((char*)&fileSize,4);
  35. }
  36. QByteArray line = file.readLine();
  37. // 计算百分比,发给主线程
  38. num +=line.size();
  39. int percent =(num*100/fileSize);
  40. emit curPercent(percent);
  41. m_tcp->write(line);
  42. }
  43. }

3.2 服务端

头文件mainwindow.h

  1. #ifndef MAINWINDOW_H
  2. #define MAINWINDOW_H
  3. #include <QMainWindow>
  4. #include <QTcpServer>
  5. QT_BEGIN_NAMESPACE
  6. namespace Ui { class MainWindow; }
  7. QT_END_NAMESPACE
  8. class MainWindow : public QMainWindow
  9. {
  10. Q_OBJECT
  11. public:
  12. MainWindow(QWidget *parent = nullptr);
  13. ~MainWindow();
  14. private slots:
  15. void on_setListen_clicked();
  16. private:
  17. Ui::MainWindow *ui;
  18. QTcpServer* m_s;
  19. };
  20. #endif // MAINWINDOW_H

源文件maindow.cpp

  1. #include "mainwindow.h"
  2. #include "ui_mainwindow.h"
  3. #include <QMessageBox>
  4. #include <QTcpSocket>
  5. #include "recvfile.h"
  6. MainWindow::MainWindow(QWidget *parent)
  7. : QMainWindow(parent)
  8. , ui(new Ui::MainWindow)
  9. {
  10. ui->setupUi(this);
  11. m_s = new QTcpServer(this);
  12. connect(m_s,&QTcpServer::newConnection,this,[=](){
  13. QTcpSocket* tcp = m_s->nextPendingConnection();
  14. // 创建子线程,tcp通过参数传递
  15. RecvFile* subThread = new RecvFile(tcp);
  16. subThread->start();
  17. connect(subThread,&RecvFile::over,this,[=](){
  18. subThread->exit();
  19. subThread->wait();
  20. subThread->deleteLater();
  21. QMessageBox::information(this,"文件接受","文件接收完毕!!!");
  22. });
  23. });
  24. }
  25. MainWindow::~MainWindow()
  26. {
  27. delete ui;
  28. }
  29. void MainWindow::on_setListen_clicked()
  30. {
  31. unsigned short port = ui->port->text().toUShort();
  32. m_s->listen(QHostAddress::Any,port);
  33. }

头文件recvfile.h

  1. #ifndef RECVFILE_H
  2. #define RECVFILE_H
  3. #include <QThread>
  4. #include <QTcpSocket>
  5. class RecvFile : public QThread
  6. {
  7. Q_OBJECT
  8. public:
  9. explicit RecvFile(QTcpSocket* tcp,QObject *parent = nullptr);
  10. protected:
  11. void run() override;
  12. private:
  13. QTcpSocket* m_tcp;
  14. signals:
  15. void over();
  16. };
  17. #endif // RECVFILE_H

源文件recvfile.cpp

  1. #include "recvfile.h"
  2. #include <QFile>
  3. RecvFile::RecvFile(QTcpSocket* tcp,QObject *parent) : QThread(parent)
  4. {
  5. m_tcp = tcp;
  6. }
  7. void RecvFile::run()
  8. {
  9. QFile* file = new QFile("recv.txt");
  10. file->open(QFile::WriteOnly);
  11. // 接收数据
  12. connect(m_tcp,&QTcpSocket::readyRead,this,[=](){
  13. static int count = 0;
  14. static int total = 0;
  15. if(count == 0){
  16. m_tcp->read((char*)&total,4);
  17. }
  18. // 读出剩余数据
  19. QByteArray all = m_tcp->readAll();
  20. count += all.size();
  21. file->write(all);
  22. if(count == total){
  23. m_tcp->close();
  24. m_tcp->deleteLater();
  25. file->close();
  26. file->deleteLater();
  27. emit over();
  28. }
  29. });
  30. // 进入事件循环
  31. exec();
  32. }

3.4 文件目录

4. 结束语

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

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

  1. 基于JAX-WS的Web Service服务端/客户端 ;JAX-WS + Spring 开发webservice

    一.基于JAX-WS的Web Service服务端/客户端 下面描述的是在main函数中使用JAX-WS的Web Service的方法,不是在web工程里访问,在web工程里访问,参加第二节. JAX ...

  2. 基于UDT connect连接通信以及文件传输--服务端

    网上与UDT相关的资料不多,与UDT相关的源码例子更少.最近在接触UDT,也是因为缺少相关的资料,导致学习起来甚感痛苦.下面将我自己这两天弄出来的代码贴出来,希望对在寻找相关资料的童鞋有一定的帮助.与 ...

  3. WCF大文件传输服务

    由于项目需要,自己写一个基于WCF的大文件传输服务雏形.觉得有一定的参考价值,因此放在网上分享. 目前版本为v1.1特点如下: 1.文件传输端口为18650 2.上传和下载文件 3.支持获取文件传输状 ...

  4. Python自带HTTP文件传输服务

    一行命令搭建一个基于python的http文件传输服务 由于今天朋友想要一个文件,而我恰好有,因为这个文件比较大,网速不是很给力,所以想到了python自己有这么一个功能,这样不仅不需要下载其他软件, ...

  5. 网站优化与Cdn文件传输服务

    网站优化与Cdn文件传输服务 如今互联网无处不在,其方便快捷.性质和低成本的经济特点,已经逐渐成为商务贸易.信息分发和数据交付的一个重要渠道.要想让数据的分发带来巨大的效益,那么网民的满意是唯一的办法 ...

  6. FTP文件传输服务

    FTP文件传输服务 一 .FTP 连接及传输的模式 l  控制连接:TCP21,用于发送FTP命令信息. l  数据连接:TCP 20, 用于上传下载数据. · 数据连接建立的类型: ·主动模式: 服 ...

  7. curl基于URL的文件传输工具

    简介 cURL是一款开源的基于URL的文件传输工具,支持HTTP.HTTPS.FTP等协议,支持POST.cookie.认证.扩展头部.限速等特性. curl命令用途广泛,比如下载.发送http请求. ...

  8. FTP 文件传输服务

    昨晚心血来潮,尝试用python写了一个ftp文件传输服务,可以接收指令,从远程ftp服务器同步指定目录数据,最后没用上,开源出来. https://github.com/jadepeng/ftp_t ...

  9. TCP/IP网络编程之基于UDP的服务端/客户端

    理解UDP 在之前学习TCP的过程中,我们还了解了TCP/IP协议栈.在四层TCP/IP模型中,传输层分为TCP和UDP这两种.数据交换过程可以分为通过TCP套接字完成的TCP方式和通过UDP套接字完 ...

随机推荐

  1. C++基于armadillo im2col的实现

    最近学习CNN,需要用到im2col这个函数,无奈网上没有多少使用armadillo的例子,而且armadillo库中似乎也没有这个函数,因此自己写了. im2col的原理网上一大把,我懒得写了. 1 ...

  2. 发现数据结构与算法之美的第n次重新学习 ——— 初遇数据结构与算法(了解)

    你的数据结构怎么学的?提起数据结构,计算机与软件,it行业内无人不知,无人不晓.但是,当你真正的去通过数据结构与算法内容去实践内容时,真的能联系起来吗?那肯定的 不管是考研还是做项目,数据结构都是必学 ...

  3. echo "This is line $LINENO"返回行号

    echo "This is line $LINENO"返回行号 LINENO 变量LINENO返回它在脚本里面的行号. #!/bin/bash echo "This is ...

  4. xrandr 直接输这个能显示可用的分辨和当前的分辨率 xrandr -s 1920x1200就设置成指定的分辨率

    利用 xrandr 命令修改屏幕分辨率 时间  2016-10-29 原文   http://blog.csdn.net/mao0514/article/details/52965700   问题背景 ...

  5. 【山外笔记-SVN命令】svn命令详解

    本文打印版文件下载地址 [山外笔记-SVN命令]svn命令详解-打印版.pdf 一.命令简介 svn命令用于Subversion命令行客户端,执行svn相关的操作. 二.命令语法 1.svn语法: ( ...

  6. SystemVerilog MCDF验证结构

    MCDF的设计和验证花费的时间:(工作中假设的时间) design  cycle time  ==10days how about 验证?verify? 模块越往上(大')验证花费的时间越来越大,但是 ...

  7. 西门子S7系列以太网通讯处理器功能介绍

    北京华科远创科技有限研发的远创智控型号ETH-YC模块适用于西门子S7-200/S7-300/S7-400.SMART S7-200.西门子数控840D.840DSL.合信.亿维PLC的PPI/MPI ...

  8. .NET Core HttpClient请求异常详细情况分析

    前言 最近项目上每天间断性捕获到HttpClient请求异常,感觉有点奇怪,于是乎观察了两三天,通过日志以及对接方沟通确认等等,查看对应版本源码,尝试添加部分配置发布后,观察十几小时暂无异常情况出现, ...

  9. Java常用集合笔记

    最近事情比较少,闲暇之余温习巩固一下Java的一些基础知识,并做一些笔记, Java常用集合, 主要参考的这篇文章:Java常用集合 ArrayList/Vertor 1. ArrayList 的主要 ...

  10. 80个Python练手项目列表

    80个Python练手项目列表   我若将死,给孩子留遗言,只留一句话:Repetition is the mother of all learning重复是学习之母.他们将来长大,学知识,技巧.爱情 ...