当前位置: 首页 > news >正文

QT中通过Tcp协议的多线程的文件传输(服务器)

首先新建一个项目命名为SendClientSever

因为要进行网络通信,在pro文件的第一行代码中添加network 

一、窗口设计

拖一个Widget里面放入label,lineEdit,pushbutton,名称如图修改

程序设计

子线程recvfile类

新建一个类用来执行子线程

将新建的类的头文件、recvfie.h文件和.cpp的继承对象改为QThread,我们后面要用到其的run函数用来实现多线程

 在recvfile.h文件中定义run函数,alt+enter可以转到cpp中添加定义因为在主线程中要创建一个RecvFile类的对象,用到其中的run进行子线程操作,要用到tcp进行通信,我们添加tcp这个参数

我们先常见一个QSoketTcp类的对象m_tcp用来接受从主线程传来的tcp

我们在再添加一个over的信号,如果文件传输完成我们就发送over这个信号给主线程

先接受从主线程传来的tcp参数

然后在recvfile.cpp在实现run函数,也就是子线程的操作

 

主线程mainwindow类

 去mianwindow中定义一个QTcpsever的指针,用来与客户端通信

 右键窗口的启动监听选择转到槽函数的clicked

实现槽函数

在构造函数中,去实例化对象,开启子线程

如果文件传输完毕就关闭子线程的操作 

完整代码

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();public slots:
};#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对象,用于接收文件并保存为"recv.txt"QFile *file = new QFile("recv.txt");// 以只写方式打开文件,如果文件已存在,将覆盖其内容file->open(QFile::WriteOnly);// 连接QTcpSocket的readyRead信号到接收数据的lambda函数connect(m_tcp, &QTcpSocket::readyRead, this, [=](){// 静态变量用于在lambda函数调用之间保持其值static int count = 0;  // 已接收的数据字节数static int total = 0;  // 总数据字节数(从文件头读取)// 如果是第一次读取数据,读取文件的总大小if(count == 0){// 从套接字中读取前4个字节,表示文件的总大小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();}});// 进入事件循环,保持线程活跃,等待readyRead信号的触发exec();
}

mainwindow.h

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

mainwindow.cpp

#include "mainwindow.h"
#include "ui_mainwindow.h"#include <QTcpSocket>
#include<QMessageBox>
#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,[=]()//如果有客户端连接就会收到一个newconnect的信号{QTcpSocket *tcp = m_s->nextPendingConnection();//通过TcpSever中的方法返回一个用于通信的套接字tcpRecvFile *subThread = new RecvFile(tcp);//实例化一个RecvFile类的对象进行子线程的操作,传入tcp参数subThread->start();//开启子线程connect(subThread,&RecvFile::over,this,[=]()//如果从RecvFlie类中收到一个over的信号,表示文件传输完成{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();//将ui中输入的端口号转换为无符号短整型存储m_s->listen(QHostAddress::Any,port);//设置监听
}

别忘了在pro代码第一行加入 network

运行实例

 我在桌面上创建了一个a.txt的文件,里面是这样的

 选择发送这个文件

 

 接受完后我们去服务器的文件夹里可以找到这个接受来的文件

打开后内容是一样的

 


http://www.mrgr.cn/news/12263.html

相关文章:

  • 3 Docker 镜像推送
  • 鸿蒙验证码,鸿蒙认证服务验证码,鸿蒙云存储上传图片
  • 华裔二、三代长相变迁的多维度解析
  • 利用深度学习技术来实现街景图像的语义分割(街景图像语义分割)
  • 如何使用 Nginx 解决跨域问题 (CORS)
  • uni-app - - - - - 自定义tabbar
  • 使用 OpenCV 组合和缩放多张图像
  • DDPM/DDIM去噪扩散概率模型和GANs
  • 查看redis节点的连接数
  • 多态(c++)
  • pytorch深度学习基础 8(CIFRA-10基础篇1)
  • 常用的 Redis 配置命令
  • 述FunsorFunsor是一个类似张量的函数和分布库。概率规划的泛函张量获取系统描述 ppl,pyro的衍生项目,人工智能python编程 ,深度神经网络
  • MyBatis之注解使用
  • 九、枚举和注解
  • npm install报错,解决记录:11个步骤诊断和解决问题
  • PowerShell | git log 中文乱码问题解决
  • Python实现t-分布随机邻域嵌入(t-SNE)降维算法
  • 使用Oracle的PL/SQL编写自定义函数来实现split
  • Java线程池