1. 效果

先看看效果图

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

  • 客户端

  • 服务端

2. 知识准备

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

还有多线程相关的知识

2.1 关于多线程

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

2.2 关于文件传输

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

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

3. 源代码

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

3.1 客户端

头文件 mainwindow.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H #include <QMainWindow> 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 <QMessageBox>
#include <QThread>
#include "sendfile.h"
#include <QFileDialog>
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 <QObject>
#include <QTcpSocket> 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 <QFile>
#include <QHostAddress>
#include <QFileInfo> 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 <QMainWindow>
#include <QTcpServer> 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 <QMessageBox>
#include <QTcpSocket>
#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 <QThread>
#include <QTcpSocket>
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 <QFile>
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. 结束语

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

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. SwiftUI 简明教程之自定义 Modifier

    本文为 Eul 样章,如果您喜欢,请移步 AppStore/Eul 查看更多内容. Eul 是一款 SwiftUI & Combine 教程 App(iOS.macOS),以文章(文字.图片. ...

  2. 手写Spring MVC框架(一) 实现简易版mvc框架

    前言 前面几篇文章中,我们讲解了Spring MVC执⾏的⼤致原理及关键组件的源码解析,今天,我们来模仿它⼿写⾃⼰的mvc框架. 先梳理一下需要实现的功能点: tomcat加载配置文件web.xml: ...

  3. J2SE基础题

    J2SE基础 八种基本数据类型的大小,以及他们的封装类.(有的也说是9中基本数据类型,包括了void) 基本类型 大小(字节) 默认值 封装类 byte 1 (byte)0 Byte short 2 ...

  4. 【BUAA软工】团队任务拆解

    项目 内容 班级:北航2020春软件工程 博客园班级博客 作业:团队任务拆解及时间规划 团队任务拆解 Alpha阶段总体规划 初步完成产品功能规格说明书中的基础功能 目前阶段仅支持本地上传文件至当前N ...

  5. [前端、HTTP协议、HTML标签]

    [前端.HTTP协议.HTML标签] 什么是前端 """ 任何与用户直接打交道的操作界面都可以称之为前端 比如:电脑界面 手机界面 平板界面 什么是后端 后端类似于幕后操 ...

  6. Nginx导航

    简介 最近都在弄微服务的东西,现在来记录下收获.我从一知半解到现在能从0搭建使用最大的感触有两点 1.微服务各大组件的版本很多,网上很多博客内容不一定适合你的版本,很多时候苦苦琢磨都是无用功 2.网上 ...

  7. [项目] 淘淘商城 Part.1

    电商 市场 2013:79万笔/分钟 2014:13.4万亿,双11支付宝交易峰值285万笔/分钟 2015:50万亿 技术特点 一个Tomcat:500并发 分布式:上万并发 高并发.集群.负载均衡 ...

  8. 【转载】kvm迁移

    https://www.jianshu.com/p/60132085a3c9 kvm分静态和动态迁移,静态就是关机迁移,比较简单,动态迁移就是不关闭服务器进行迁移.静态迁移:确定虚拟机关闭 https ...

  9. 马哥Linux SysAdmin学习笔记(三)

    CentOS 5和6的启动流程: Linux:kernel+rootfs kernel:进程管理,内存管理,网络管理,驱动程序,文件系统,安全功能 rootfs: glibc 库:函数集合,funct ...

  10. Zabbix 架构

    Zabbix 架构 1.Zabbix Server Zabblx server是agent程序报告系统可用性.系统完整性和统计数据的核心组件,是所有配置信息.统计信息和操作数据的核心存储器. 2.Za ...