QT中通过TCP协议多线程的文件传输(客户端)

news2024/9/20 19:27:03

首先,新建一个项目,我命名为了SendFileClient

 首先我们要在pro文件中 代码第一行加入network的后缀

 

一、窗口搭建

 如图所示,在第一个QWidget中让客户端输入IP端口号   连接服务器

第二个Qwidget 设置一个LineEdit,供客户端选择要发送的文件

在下面设置一个 progressBar ,用来显示文件上传的进度

在最下面设置一个按钮点击发送文件。

二、创建一个新类

既然运用到了多线程,我们将连接服务器,选择文件,发送文件的任务交给子线程,主线程去管理进度条的任务

右键项目add new新建一个类 

继承Qobject,这里我取名为sendfile

在sendfile.h中定义两个函数用来连接服务器,发送文件

mainwindow的操作

连接服务器

首先在mainwindow的构造函数中 初始化 ip ,端口号进度条 的值

我要将发送文件连接服务器在子线程中操作的话,我们就要先创建一个线程对象和任务对象,将任务对象通过moveToThread函数移动到创建出来的线程中去工作。

 接下来我们实现 连接服务器的操作

右键ui中的连接服务器转到槽函数的clicked()

 函数中的内容

 要提前在mainwindow.h在定义一个信号,提醒worker对象中的connectSever开始执行

 

 在上面的构造函数中,用connect如果收到startConnect的信号,就去执行woker中的connectSever函数

然后启动子线程用start()

看到这先去看sendfile操作再回来看下面的  1

 这时主线程收到了子线程发来的connectOK,就知道成功连接到了服务器
如果收到了gameover,就知道服务器断开了,进行资源释放

发送文件

给选择文件添加一个处理函数 

发送文件同样

 提前在mainwindow.h中添加好这个信号

 在mainwindow的构造函数中添加一个connect表示如果我收到了发来的sendfile信号,就去完成sendfile类中的send函数

这里跳转到sendfile后面观看  2

 更新进度条

在构造函数中添加connect,如果收到curpencent信号,将信号中传来的pencent去设置进度条的值

mainwindow到这也结束了

sendfile的操作

1

现在sendfile.h文件中定义一个QTcpSocket的套接字,用于通信

 

 完善一下connectSever操作

 提前在sendfile.h中先定义好信号;

第一次看到这可以回去看了

2

将文件发送给服务器,将文件传输进度通过信号告诉主线程

提前添加一个curpencent的信号

这时回到主窗口更新进度条,senfile到这一步就完成了

完整代码

mainwindow.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include"sendfile.h"
#include<QThread>

namespace Ui {
class MainWindow;
}

class MainWindow : public QMainWindow
{
    Q_OBJECT

signals:
    void startconnect(unsigned short ,QString);
    void sendfile(QString path);

public:
    explicit MainWindow(QWidget *parent = nullptr);
    ~MainWindow();


private slots:
    void on_pushButton_clicked();

    void on_selFile_clicked();

    void on_sendFile_clicked();

private:
    Ui::MainWindow *ui;
    QThread *t;
    sendFile * work;
};

#endif // MAINWINDOW_H

mainwindow.cpp

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include<QMessageBox>
#include<QFileDialog>
MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    ui->ip->setText("127.0.0.1");
    ui->port->setText("8899");
    ui->progressBar->setRange(0,100);
    ui->progressBar->setValue(0);

    t = new QThread;
    work = new sendFile; //实例化一个sendfile类

    work->moveToThread(t);//将实例化的类要执行的程序移动到线程里去执行

    connect(this,&MainWindow::sendfile,work,&sendFile::send);

    connect(this,&MainWindow::startconnect,work,&sendFile::connectSever);//如果点击连接按钮,这里会接收到一个startconnct的槽函数,然后去执行work中的connctSever操作

    connect(work,&sendFile::connectOK,this,[=](){ //如果connctsever连接成功,会发来一个connctok的槽函数
        QMessageBox::information(this,"连接服务器","连接服务器成功");
    });
    connect(work,&sendFile::gameover,this,[=](){  //如果断开连接会发来一个gameover的槽函数
        t->quit();
        t->wait();
        t->deleteLater();
        work->deleteLater();
    });
    connect(work,&sendFile::curpencent,ui->progressBar,&QProgressBar::setValue);
    t->start();
}


MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::on_pushButton_clicked()
{
    unsigned short port = ui->port->text().toUShort();//将ui中的端口号转换为short类型取出保存
    QString ip = ui->ip->text().toUtf8();//将对象转换为UTF-8编码的字节序列,存储在QString对象中,
    emit startconnect(port,ip);//发送一个开始连接的信号
}

void MainWindow::on_selFile_clicked()
{
    QString path = QFileDialog::getOpenFileName();//通过此方法可以得到某个磁盘文件的绝对路径
    if(path.isEmpty())
    {
        QMessageBox::warning(this,"选择文件","选择的文件不能为空");//如果选择文件为空弹出一个警告对话窗
        return;
    }
    ui->filePath->setText(path);//将选择好的文件设置给文本框
}

void MainWindow::on_sendFile_clicked()
{
    emit sendfile(ui->filePath->text());//因为发送文件的操作是在子线程中做的,所以发送一个信号告诉子线程文件路径名
}

sendfile.h

#ifndef SENDFILE_H
#define SENDFILE_H

#include <QObject>
#include<QTcpSocket>
#include <QHostAddress>

class sendFile : public QObject
{
    Q_OBJECT
public:
    explicit sendFile(QObject *parent = nullptr);

    void connectSever(unsigned short port, QString ip);//连接服务器

    void send(QString path);//发送文件

signals:

    void connectOK();
    void gameover();

    void curpencent(int );

private:
    QTcpSocket *tcp;


};

#endif // SENDFILE_H

sendfile.cpp

#include "sendfile.h"
#include <QFile>
#include <QFileInfo>
#include <QHostAddress>


sendFile::sendFile(QObject *parent) : QObject(parent)
{

}

void sendFile::connectSever(unsigned short port, QString ip)
{
    tcp = new QTcpSocket;//实例化套接字
    tcp->connectToHost(QHostAddress(ip),port);//通过给定的ip,port连接服务器

    connect(tcp,&QTcpSocket::connected,this,&sendFile::connectOK);//如果连接成功就发送一个connectOK的信号告诉主线程
    connect(tcp,&QTcpSocket::disconnected,[=](){//如果断开连接就关闭套接字并释放,发送gameover的信号给主线程

        tcp->close();
        tcp->deleteLater();
        emit  gameover();
    });
}

void sendFile::send(QString path)
{
    // 创建一个QFile对象,将要发送的文件与该对象关联
    QFile file(path);
    QFileInfo info(path);// 创建一个QFileInfo对象,用于获取文件的元信息,如大小等

    file.open(QFile::ReadOnly); // 打开文件为只读模式
    int fileSize = info.size();// 获取文件的大小
    while(!file.atEnd())// 当文件未读到末尾时,循环读取文件
    {
        static int num = 0; // 定义一个静态变量num,用于累计已读取的字节数
        if(num == 0)// 如果是第一次读取,则发送文件的大小信息
        {
            tcp->write((char *)&fileSize, 4);// 将文件大小的前4个字节写入tcp套接字,以通知接收端文件的大小
            num = 4;// 将静态变量num设置为4,因为已经发送了文件大小的前4个字节
        }
        QByteArray line = file.readLine(); // 读取一行数据
        num += line.size();// 将读取的字节数累加到num
        int percent = (num * 100 / fileSize); // 计算已读取的字节数占总字节数的百分比
        tcp->write(line);// 将读取的数据行写入tcp套接字
        emit curpencent(percent);// 发射信号,通知界面文件传输的进度
    }
}

main.cpp

#include "mainwindow.h"
#include <QApplication>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    MainWindow w;
    w.show();

    return a.exec();
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2064164.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

二维中,若直线上两点q1和q2,输入一个点P1,求P1在直线上的垂点

一、计算过程 在二维空间中&#xff0c;若给定直线上两点Q1和Q2以及一个点P1&#xff0c;要求出点P1在直线上的垂点&#xff0c;可以通过以下步骤进行&#xff1a; ‌1、判断点P1是否在直线q1-q2上‌&#xff1a; 首先&#xff0c;需要判断点P1是否位于直线Q1-Q2上。这可以通过…

【Linux】实现三个迷你小程序(倒计时,旋转指针,进度条)

&#x1f984;个人主页:修修修也 &#x1f38f;所属专栏:Linux ⚙️操作环境:Xshell (操作系统:CentOS 7.9 64位) 目录 &#x1f4cc;倒计时小程序 &#x1f38f;项目效果展示 &#x1f38f;项目实现思路 &#x1f38f;项目完整代码 &#x1f4cc;旋转指针小程序 &#x…

视频监控接入汇聚平台如何根据客户要求定制资源树结构和资源的任意排序

目录 一、需求描述 1.1视频监控资源树 1.2客户要求 二、市场上产品常用处理方法 2.1 常用处理方法 &#xff08;1&#xff09;按笔画数排序 &#xff08;2&#xff09;按拼音排序 &#xff08;3&#xff09;按字典序排序 &#xff08;4&#xff09;按首字母排序 2.2 …

使用预训练的 ONNX 格式的目标检测模型(基于 YOLOv8n-pose)姿态监测

具体步骤如下&#xff1a; 加载图像&#xff1a; 从指定路径读取一张图像&#xff08;这里假设图像名为bus.jpg&#xff09;。将图像从 BGR 颜色空间转换为 RGB 颜色空间。 图像预处理&#xff1a; 计算图像的高度、宽度&#xff0c;并确定其中的最大值作为新图像的边长。创建一…

C语言新手小白详细教程:冒泡排序

&#x1f30f;个人博客主页&#xff1a;意疏-CSDN博客 希望文章能够给到初学的你一些启发&#xff5e; 如果觉得文章对你有帮助的话&#xff0c;点赞 关注 收藏支持一下笔者吧&#xff5e; 阅读指南&#xff1a; 开篇说明冒泡排序简介冒泡排序代码 开篇说明 本文我们来介绍冒…

编码器精度

系列文章目录 1.元件基础 2.电路设计 3.PCB设计 4.元件焊接 5.板子调试 6.程序设计 7.算法学习 8.编写exe 9.检测标准 10.项目举例 11.职业规划 文章目录 前言一、影响因素二、编码器精度三、位置因素四、环境因素五、磁编码器 前言 送给大学毕业后找不到奋斗方向的你&…

《九界ol游戏源码》(游戏源码+客户端+服务端+工具+视频教程)百度云盘下载

游戏制作精美&#xff0c;和天龙八部用一样的游戏引擎&#xff0c;就是ogre。有兴趣的朋友&#xff0c;可以下载来收藏研究。 《九界ol游戏源码》&#xff08;游戏源码客户端服务端工具视频教程&#xff09; 下载地址&#xff1a; 链接: https://pan.baidu.com/s/1KIWSVYyAcSpY…

案例分享—医疗行业国外优秀界面设计案例

医疗行业UI网页设计需注重用户体验与可访问性&#xff0c;确保页面布局清晰、导航简洁明了&#xff0c;以便用户快速找到所需信息。同时&#xff0c;设计应符合医疗行业规范&#xff0c;传递出专业、可信的形象。 在医疗行业UI网页设计中&#xff0c;色彩搭配与视觉元素的选择至…

【大模型从入门到精通35】开源库框架LangChain 利用LangChain构建聊天机器人2

这里写目录标题 利用LangChain构建具备记忆功能的对话检索链设置对话历史记忆构建对话检索链处理问题并生成答案 创建基于文档的问答聊天机器人初始设置和导入文档加载和处理 利用LangChain构建具备记忆功能的对话检索链 设置对话历史记忆 为了使问答系统能够记住对话的上下文…

计算机网络-2-tcpip协议

1.说说 TCP/IP 四层模型&#xff1f; TCP/IP&#xff08;Transmission Control Protocol/Internet Protocol&#xff09;模型是一种用于描述互联网通信的协议层次结构。它分为四个主要层次&#xff0c;每个层次都定义了不同的协议来实现特定的功能。下面是TCP/IP模型各层的常用…

PCIE-flit mode retry

下一个即将发送的seq num: 下一个即将发送的ack或者nak的seq num: Tx发送exp seq num的个数: Tx发送nak的个数 下一个期望收到的flit的seq num&#xff0c;注意是指下个期望收到的有效的、non-idle、non_duplictae的flit: 收到的flit的真实的seq num&#xff08;implicit…

控制台小游戏—扫雷

引言&#xff1a; 在前面一篇中&#xff0c;小编介绍了如何将代码分装在多个文件中的操作。在本篇文章中&#xff0c;小编将介绍一个广受欢迎的小游戏&#xff0c;以帮助大家熟悉这个操作。这个小游戏不仅可以让我们熟悉将代码放在多个文件中的操作&#xff0c;还可以加深我们…

PPT时间轴怎么做?用这款AI软件一键快速生成!

当ppt中需要呈现时间顺序、发展历程甚至是沧海桑田的变化时&#xff0c;很多人都会首选ppt时间轴这种视觉化的方式&#xff0c;它简洁直观&#xff0c;让人可以快速领会ppt想表达的意图&#xff0c;达到一图胜千言的目的。 对于不擅长制作ppt时间轴的人&#xff0c;最好的方式…

2024买一个机械硬盘

1997年&#xff0c;博主配了第一个电脑&#xff0c;CPU是6X86, 您可能没有听说过&#xff0c;那时的硬盘只有2GB~4GB&#xff0c;侯杰在深入浅出MFC中说以后要有大颗的硬盘&#xff0c;当时感觉看到这个单位来描述硬盘&#xff0c;感觉挺有意思。1999年&#xff0c;博主在电脑城…

mujoco_py ERROR: GLEW initalization error: Missing GL version

1. 问题描述&#xff1a; 运行mujoco ROS节点的时候&#xff0c;遇到错误如下&#xff1a; from pkg_resources import load_entry_point Creating window glfw ERROR: GLEW initalization error: Missing GL version 2. 解决方法 在./bashrc文件中添加&#xff1a; export L…

Vue状态管理工具:Pinia

基本概念 Pinia 是一个专为 Vue.js 设计的状态管理库&#xff0c;特别是针对 Vue 3 进行了优化&#xff0c;完美支持Vue3的Composition api 以及TypesCcript语法。它提供了一种更加简单、直观且可扩展的方式来组织和访问应用程序的状态。目前Pinia已经取代Vuex成为vue官方文档…

总结:数字图像处理基础知识

数字图像处理中的图像坐标系是理解图像数据结构和图像处理算法的基础。在计算机视觉和图像处理领域&#xff0c;通常有两种主要的坐标系统用于描述图像中的像素位置&#xff1a;笛卡尔坐标系和像素坐标系。下面我将详细介绍这两种坐标系统及其在数字图像处理中的应用。 1. 笛卡…

T/CECS 10035-2019 绿色建材评价 金属复合装饰材料

一、绿色建材 绿色建材是指在全生命周期内减少对天然资源消耗和减轻对生态环境影响&#xff0c;具有节能、减排、安全、便利和可循环的建材产品&#xff0c;获得绿色产品证书的产品在实际招投标以及品牌宣传中具有绝对优势。 二、认证模式 初始工厂检查产品抽样检验获证后监督…

稳压二极管、肖特基二极管、TVS管、静电ESD管的区别

1.稳压二极管 正向导通电压跟普通二级管一样约为0.7v&#xff0c;反向状态下在临界电压之前截止&#xff0c;在达到临界电压的条件下会处于导通的状态&#xff0c;电压也不再升高&#xff0c;所以用在重要元器件上&#xff0c;起到稳压作用。 稳压二极管主要利用其反向击穿时…