首页 > 其他分享 >QT中通过Tcp协议的多线程的文件传输(服务器)

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

时间:2024-08-23 23:21:49浏览次数:13  
标签:文件 RecvFile 多线程 QT 文件传输 tcp 线程 include MainWindow

首先新建一个项目命名为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_OBJECT

public:
    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中的方法返回一个用于通信的套接字tcp
        RecvFile *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的文件,里面是这样的

 选择发送这个文件

 

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

打开后内容是一样的

 

标签:文件,RecvFile,多线程,QT,文件传输,tcp,线程,include,MainWindow
From: https://blog.csdn.net/BEIFEN13/article/details/141440043

相关文章

  • QT中常用类的成员(2024.8.20更新)
    QT中常用类的成员1.QObject类是Qt框架中所有对象的基类,提供了信号和槽机制、事件处理、对象树和内存管理等功能2.QMetaObject类是Qt框架中用于描述对象的元数据的类,提供了元数据查询、类信息、属性信息、方法信息等功能QWidget类是Qt框架中所有图形用户界面组件......
  • Qt (9)【Qt窗口 —— 如何在窗口中创建菜单栏和工具栏】
    阅读导航引言一、Qt窗口简介二、如何在窗口中创建菜单栏1.创建菜单栏2.在菜单栏中添加菜单3.创建菜单项4.在菜单项之间添加分割线三、如何在窗口中创建工具栏1.创建工具栏2.设置停靠位置3.设置浮动属性4.设置移动属性引言在上一篇文章中,我们深入探讨了Qt框......
  • 开发多线程程序时,需要注意那些问题
    线程安全竞态条件(RaceCondition):当多个线程同时访问和修改共享资源时,可能会出现竞态条件,导致不确定的行为。需要通过同步机制(如互斥锁、读写锁、原子操作)来保护共享资源。死锁(Deadlock):当两个或多个线程相互等待对方释放锁时,程序会陷入死锁状态。避免死锁的一些策略包括:避......
  • Qt+OpenGL混合两个纹理,并可以改变纹理透明度
    一、概述需求:1.将两纹理进行融合,改变其中一个透明度让其渐渐显示或隐藏2.控制x轴像素互换,让笑脸达到向左看或向右看的目的。 大部分的代码都是常规代码。还是那一套流程:1.定义顶点、纹理、顶点索引坐标。2.创建并绑定VAO、VB......
  • QT+OpenGL纹理与颜色混合
    一、概述使用OpenGL将纹理与颜色混合输出。ps:此处并无实际的意义只是单纯的为了好玩。步骤:1.定义顶点坐标、颜色、纹理及顶点索引floatvertices[]={//----位置---------颜色------纹理坐标-1.0f,1.0f,0.0f,1.0......
  • Qt实现画图板
    Qt实现画板基于QGraphicsView实现绘画曲线注意点_qgraphicsview绘制曲线图-CSDN博客Qt桌面白板工具其一(解决曲线不平滑的问题——贝塞尔曲线)_qt贝塞尔曲线-CSDN博客先实现一个最简单的不考虑任何优化的曲线画板我们知道鼠标移动时,会在其移动轨迹上留下一系列的点,我们可以将这......
  • 【Qt】Qt窗口 | QDialog 对话框
    文章目录一.对话框二.对话框的分类1.非模态对话框2.模态对话框3.混合属性对话框三.自定义对话框1.代码实现2.ui文件实现四.内置对话框1.QMessageBox消息对话框2.QColorDialog颜色对话框3.QFileDialog文件对话框4.QFontDialog字体对话框5.QInputDialo......
  • Qt5.14.2 多边形与多边形求交集
    利用Qt5.14.2中自带的QPolygonF类的intersected()函数求两个多边形的交集多边形。inlineQList<QPolygonF>getPolygonIntersectedWithPolygon(QPolygonFpolygon1,QPolygonFpolygon2){QList<QPolygonF>outval;//此处求出的intersection可能包含多个子......
  • 在Java中实现通过TCP方式发送和接收Socket消息,包含在多线程状态下的实现
    导言:公司的代码,本来客户端client是前端的unity发送请求的,后面自己写的时候需要在本地进行测试,所以也用Java实现了前端,就写出来记录一下。本文主要展示客户端client跟服务端server基础代码,里面的一些业务逻辑没有进行展示正文1.创建client端首先我们需要创建一个client端进......
  • qt5.14.2 MSVC opencv(不结合vs)路径添加问题 测试通过
     不换行写法1win32:CONFIG(release,debug|release):LIBS+=-LG:/opencv4.4.0/opencv4.4_vs_msvc19_qt6.5/x64/vc17/lib/-lopencv_aruco440-lopencv_bgsegm440-lopencv_bioinspired440-lopencv_calib3d440-lopencv_ccalib440-lopencv_core440-lopencv_cvv440-lopen......