qt客户端与服务端关于传输文件

news2024/9/23 14:28:39

如果直接发 发送的数据永远要比接受的块 需要有时间间隔 此时定时器的作用就显现出来了

发送数据都先发头,要保证服务器发送的头,客户端能接受到

发送数据后不要直接读数据,加一个延迟

这里以##作为分隔符

发送多少读多少,

发送数据的操作

QT网络编程中关于发送文件的操作函数  规则就是从文件中读取多少就发送多少
void ServerWidget::senddata()
{

    qint64 len =0;
    do
    {
        //每次读4k的内容
        char buf[4*1024] ={0};
    len =  file.read(buf,sizeof(buf));  //read函数返回值为qint64
    //读多少发多少
    len =socket->write(buf,len); //统计的发送数据

    sendsize+=len;
//累积的文件大小
    }while(len>0);

    //判断文件发送完毕和总的文件作比较即可
    if(sendsize==filesize)
    {
        //提示用户
        ui->textEdit->append("文件已发送完毕");
        file.close();
        //发送完毕后断开连接 ,以免丢包
//建立好的通讯套接字断开连接
        socket->disconnectFromHost();
        socket->close();
    }
}

这个函数调用前需要有定时器的相关操作

需要先激活定时器 先发送头  间隔20ms发送

void ServerWidget::on_butsend_clicked()
{
    //发送文件头信息
    QString head = QString("%1##%2").arg(filename).arg(filesize);
    qint64 len =    socket->write(head.toUtf8()); // write函数返回值为qint64
    if(len>0)
    {
        // qDebug()<<"发送成功";
        timer->start(20);

    }else
    {
        qDebug()<<"发送信息失败";
        file.close();
        ui->butselect->setEnabled(1);
        ui->butselect->setEnabled(0);
    }


}

在选择按钮的函数中调用connect()关联信号和槽

void ServerWidget::on_butselect_clicked()
{
    // QString getOpenFileName(QWidget *parent = nullptr, const QString &caption = QString(), const QString &dir = QString(), const QString &filter = QString(), QString *selectedFilter
    QString path = QFileDialog::getOpenFileName(this,"打开文件","../");
    if(path.isEmpty()==false)
    {
        //路径不为空的话就打开该文件
        //每次选择文件的时候将文件名和大小清空
        filename.clear();
        filesize =0;
        QFileInfo info(path);

        //QFileInfo中有文件信息的成员函数
        // file.open();
        filename = info.fileName(); //获取文件名字
        filesize = info.size();//获取文件大小

        //用变量来标记文件发送了多少  防止丢包

        sendsize =0 ;
        //指定文件名字,只读方式打开文件按

        file.setFileName(path);

        if(!file.open(QIODevice::ReadOnly))
        {
            qDebug()<<"只读方式打开文件失败"<<'\n';
        }


        //提示用户打开文件的路径
        ui->textEdit->append(path);
        ui->butselect->setEnabled(false);

        ui->butselect->setEnabled(true);


    }else
    {
        qDebug()<<"选择文件无效"<<'\n';
    }

    connect(timer,&QTimer::timeout,[=](){

        timer->stop();
        senddata();
    });
}

客户端:

#include "clientwidget.h"
#include "ui_clientwidget.h"
#include <QMessageBox>
#include <QHostAddress>
Clientwidget::Clientwidget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Clientwidget)
{
    ui->setupUi(this);
    setWindowTitle("客户端");
    //ui->progressBar->setValue(0);//设置进度条的值
    isstart = true;
    csocket = new QTcpSocket(this);


    connect(csocket,&QTcpSocket::readyRead,[=](){

        QByteArray buf = csocket->readAll();
        if(true==isstart)
        {
            isstart = false;
            //初始化
            filename = QString(buf).section("##",0,0);
            filesize = QString(buf).section("##",1,1).toInt();
            recivesize =0;
            //打开文件

            file.setFileName(filename);
            bool isok = file.open(QIODevice::WriteOnly);
            if(false ==isok)
            {
                qDebug()<<"write only errno 29";
            }
            QString str = QString("接受的文件:[%1:%2kb]").arg(filename).arg(filesize/1024);

            QMessageBox::information(this,"文件信息",str);

            ui->progressBar->setMinimum(0);
            ui->progressBar->setMaximum(100);
            ui->progressBar->setValue(0);

        }
        else
        {
            qint64 len = file.write(buf);
            if(len>0)
            {
                 recivesize+=len;
                QString str = QString::number(recivesize);
                 csocket->write(str.toUtf8().data());
                //qDebug()<<len;
            }
            ui->progressBar->setValue(recivesize/1024);

            if(recivesize==filesize)
            {
                csocket->write("file done");
           QMessageBox::information(this,"提示","文件接受完成");
                file.close();


                csocket->disconnectFromHost();
                csocket->close();
                return ;
            }
        }
    });



    /*
String::section() 是 Qt 中 QString 类的一个成员函数,用于从字符串中提取指定范围内的子字符串。它可以根据分隔符或索引位置来提取子字符串。

QString::section() 函数签名
QString section(QChar sep, int startIndex, int endIndex, QString::SectionFlags flags = KeepEmptyParts) const;

参数说明
sep:分隔符,用于分割字符串。
startIndex:起始索引,表示从第几个分隔符开始提取。
endIndex:结束索引,表示到第几个分隔符结束提取。
flags:标志位,控制如何处理空的部分,默认为 KeepEmptyParts。
返回值
返回一个 QString,包含了从 startIndex 到 endIndex 之间的子字符串。
        */
}

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

void Clientwidget::on_butconnect_clicked()
{
    QString ip = ui->ipedit->text();

    quint64 port = ui->portedit->text().toInt();
    csocket->connectToHost(QHostAddress(ip),port);
}



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

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

相关文章

启程与远征Ⅲ--很棒的大语言模型代理

这是关于什么的&#xff1f; 这篇 Awesome-LLM-Agents 是对 Agentic AI 上的最新里程碑论文和开源项目的深度优先回顾。 这个 Awesome-LLM-Agents 项目是我在LLM-Agents-in-Production主题上建立专业知识的第一步&#xff0c;我打算将这个故事用作知识库&#xff0c;记录项目…

Unity转Unreal5从入门到精通之不同的Actor之间如何交互

前言 Unreal不同的Actor蓝图之间如何交互 当我们使用蓝图时&#xff0c;当碰到交互的时候&#xff0c;可能会有点蒙&#xff0c;平时我们写代码&#xff0c;A调用B的函数&#xff0c;非常简单。那么在蓝图中&#xff0c;我们如何调用呢&#xff1f;下面我们来一一讲解 通过函…

html+css+js网页制作 京东首页官网 ui还原度100%

htmlcssjs网页制作 京东首页官网 ui还原度100% 网页作品代码简单&#xff0c;可使用任意HTML编辑软件&#xff08;如&#xff1a;Dreamweaver、HBuilder、Vscode 、Sublime 、Webstorm、Text 、Notepad 等任意html编辑软件进行运行及修改编辑等操作&#xff09;。 获取源码 …

530系列变频器ACS530-01-363A-4可议价

530系列变频器ACS530-01-363A-4可议价 530系列变频器ACS530-01-363A-4可议价 530系列变频器ACS530-01-363A-4可议价 530系列变频器ACS530-01-363A-4引脚线 530系列变频器ACS530-01-363A-4说明书 530系列变频器ACS530-01-363A-4电路图 ACS530-01-363A-4变频器功率的选用 A…

融合创新:EasyCVR视频汇聚平台云计算技术与AI技术共筑雪亮工程智能防线

随着信息技术的飞速发展&#xff0c;视频云计算技术作为云计算领域的一个重要分支&#xff0c;正逐步在公共安全、社会治理等领域展现出其独特的优势。特别是在雪亮工程这一群众性治安防控工程中&#xff0c;视频云计算技术更是发挥了不可替代的作用。本文将从视频云计算技术的…

HarmonyOS开发案例:列表场景实例-TaskPool

介绍 本实例通过列表场景实例讲解&#xff0c;介绍在TaskPool线程中操作关系型数据库的方法&#xff0c;涵盖单条插入、批量插入、删除和查询操作。 效果图预览 使用说明 进入页面有insert(单条数据插入)、batch insert(批量数据插入)、query(查询操作)三个按钮&#xff0c;…

6.7分不降反升的IEEE trans:“江湖地位”超稳的1区,离TOP还有多远?

本周投稿推荐 SCI&EI • 1区计算机水刊&#xff0c;3.5-4.0&#xff08;48天录用&#xff09; • 2区-Top水刊&#xff0c;2.0-3.0&#xff08;沾边可录&#xff09; • 能源电力水刊&#xff0c;无版面费&#xff08;25天录用&#xff09; EI • 各领域沾边均可&…

PyTorch--残差网络(ResNet)在CIFAR-10数据集进行图像分类

完整代码 import torch import torch.nn as nn import torchvision import torchvision.transforms as transforms# Device configuration device torch.device(cuda if torch.cuda.is_available() else cpu)# Hyper-parameters num_epochs 80 batch_size 100 learning_rate…

星地多网融合调度平台:高效融合,智慧救援

在应急救援领域&#xff0c;通信的畅通无阻是保障救援行动成功的关键。然而&#xff0c;面对复杂多变的救援环境和多样化的通信需求&#xff0c;传统的通信系统往往难以满足现代应急救援的高标准要求。为了克服这些挑战&#xff0c;星地多网融合调度平台应运而生&#xff0c;它…

【大模型理论篇】生成式模型算法原理深入浅出

1. 背景介绍 随着大模型的推出&#xff0c;“生成式AI”这个名词一夜之间席卷大江南北。甚至很多人的概念里&#xff0c;“生成式AI”等同于人工智能。但事实上&#xff0c;人工智能(Artificial Intelligence)涵盖的范围要广的多&#xff0c;生成式AI只是其中的一个部分&#x…

SpringBoot教程(二十一) | SpringBoot实现单点定时任务之@Scheduled

SpringBoot教程&#xff08;二十一&#xff09; | SpringBoot实现单点定时任务之Scheduled 前言巨坑&#xff08;Scheduled任务都用了同一个线程去执行&#xff0c;导致定时任务存在堵塞&#xff09;解决办法一&#xff1a;添加自定义的ThreadPoolTaskScheduler配置&#xff08…

html+css 实现hover 换背景跳动按钮

前言:哈喽,大家好,今天给大家分享html+css 实现hover 换背景跳动按钮!并提供具体代码帮助大家深入理解,彻底掌握!创作不易,如果能帮助到大家或者给大家一些灵感和启发,欢迎收藏+关注哦 💕 目录 📚一、效果📚二、原理解析💡这个按钮hover后,有4个变化:📝1.1…

【C++二分查找】2080. 区间内查询数字的频率

本文涉及的基础知识点 C二分查找 LeetCode2080. 区间内查询数字的频率 请你设计一个数据结构&#xff0c;它能求出给定子数组内一个给定值的 频率 。 子数组中一个值的 频率 指的是这个子数组中这个值的出现次数。 请你实现 RangeFreqQuery 类&#xff1a; RangeFreqQuery(i…

eclipse免安装版64位(专业的Java 开发工具 2018版本)

前言 eclipse是一个开放源代码的、基于Java的可扩展开发平台。就其本身而言&#xff0c;它只是一个框架和一组服务&#xff0c;用于通过插件组件构建开发环境。 一、下载地址 下载链接&#xff1a;分享文件&#xff1a;eclipse v2018.zip 二、安装步骤 1、下载解压后将ecl…

动手学深度学习(pytorch)学习记录7-线性回归的从零开始实现[学习记录]

注&#xff1a;本代码在jupyter notebook上运行 封面图片来源 1、生成数据集 %matplotlib inline import random import torch from d2l import torch as d2l构造数据集&#xff1a;生成一个包含1000个样本的数据集&#xff0c; 每个样本包含从标准正态分布中采样的2个特征。…

【JavaEE】线程池和定时器

&#x1f525;个人主页&#xff1a; 中草药 &#x1f525;专栏&#xff1a;【Java】登神长阶 史诗般的Java成神之路 ✏️一.线程池 在Java中&#xff0c;线程池&#xff08;Thread Pool&#xff09;是一种用于管理并发线程的机制&#xff0c;它提供了一种创建、复用和管理一组…

【C++】一文掌握C++的四种类型转换 --- static_cast、reinterpret_cast、const_cast、dynamic_cast

当面对两个选择时&#xff0c;抛硬币总能奏效。 并不是因为它总能给出对的答案&#xff0c; 而是在你把它抛在空中的那一秒里。 你突然就知道&#xff0c;你希望的结果是什么了。 --- 曾小贤 《爱情公寓》--- 一文掌握C的四种类型转换 1 C中的类型2 类型转换3 四种类型转换…

一次caffeine引起的CPU飙升问题

背景 背景是上游服务接入了博主团队提供的sdk&#xff0c;已经长达3年&#xff0c;运行稳定无异常&#xff0c;随着最近冲业绩&#xff0c;流量越来越大&#xff0c;直至某一天&#xff0c;其中一个接入方&#xff08;流量很大&#xff09;告知CPU在慢慢上升且没有回落的迹象&…

Godot《躲避小兵》实战之创建玩家场景

项目设置完之后&#xff0c;我们就可以开始处理玩家控制的角色。 这里我们将玩家放在一个单独的场景当中&#xff0c;这样做的好处是在游戏的其他部分做出来之前&#xff0c;我们就可以对其进行单独测试。 节点结构 场景是一个节点树结构&#xff0c;因此一个场景需要有一个…

设计模式六大原则之:依赖倒置原则

1. 依赖倒置原则简介 依赖倒置原则(Dependency Inversion Principle, DIP) 是面向对象设计的核心原则之一&#xff0c;由罗伯特马丁(Robert C. Martin)提出&#xff0c;旨在降低类间的依赖度&#xff0c;使之更易于维护和扩展。该原则主张高层模块不应该依赖于底层模块&#x…