QT TCP传输文件+ui

news2024/9/21 2:47:32

TCPFile

tcp协议传输文件

在这里插入图片描述

TCPFile.pro

QT       += core gui network

clientwidget.h

#include <QWidget>
#include <QTcpSocket>  // 通信套接字
#include <QFile>

private slots:
    void on_pushButton_clicked();

private:
    

    QTcpSocket *tcpSocket;

    QFile file; // 文件对象
    QString fileName; // 文件名字
    qint64 fileSize;  // 文件大小
    qint64 recvSize;  // 已经接收文件的大小

    bool isStart;  // 标志位

widget.h

#include <QTcpServer>  // 监听套接字
#include <QTcpSocket>  // 通信套接字
#include <QFile>
#include <QTimer>

public:
    

    void sendData(); // 发送文件数据

private slots:
    void on_pushButton_clicked();

    void on_pushButton_2_clicked();

private:
    

    QTcpServer *tcpServer;
    QTcpSocket *tcpSocket;
    QFile file; // 文件对象
    QString fileName; // 文件名字
    qint64 fileSize;  // 文件大小
    qint64 sendSize;  // 已经发送文件的大小

    QTimer timer;  // 定时器

clientwidget.cpp


#include <QDebug>
#include <QMessageBox>
#include <QHostAddress>

Clientwidget::Clientwidget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::Clientwidget)
{
    ui->setupUi(this);

    isStart = true;

    tcpSocket = NULL;

    // 分配空间,指定父对象
    tcpSocket = new QTcpSocket(this);

    setWindowTitle("客户端");

    // 进度条
    ui->progressBar->setValue(0);  //  当前值

    connect(tcpSocket, &QTcpSocket::readyRead, [=](){
       // 取出接收内容
        QByteArray buf = tcpSocket->readAll();

        if(true == isStart)
        { // 接收头信息
            isStart = false;

            // 解析头部信息 举例:

            // QString str = "hello##1024";
            // str.section("##", 0, 0);

            // 初始化
            fileName = QString(buf).section("##", 0, 0);
            fileSize = QString(buf).section("##", 1, 1).toInt();
            recvSize = 0;

            // 打开文件
            file.setFileName(fileName);

            bool isOK = file.open(QIODevice::WriteOnly);
            if (false == isOK){
                qDebug() << "WriteOnly error";
            }

            // 设置进度条
            ui->progressBar->setMinimum(0); // 最小值
            ui->progressBar->setMaximum(fileSize/1024); // 最大值
            ui->progressBar->setValue(0);  //  当前值

        }
        else { // 文件信息
            qint64 len = file.write(buf);
            if(len > 0){  // 接收数据大于0
                recvSize += len;  // 累加接收大小
                qDebug() << len;
            }

            ui->progressBar->setValue(recvSize/1024);  // 更新进度条

            if(recvSize == fileSize){  // 文件接收完毕

                file.close();
                QMessageBox::information(this, "完成", "文件接收完成");
                // 给服务器发送 接收文件完成的信息
                tcpSocket->write("file done");

                tcpSocket->disconnectFromHost();
                tcpSocket->close();
            }
        }
    });

}

void Clientwidget::on_pushButton_clicked()
{
    // 获取服务器ip和端口
    QString ip = ui->lineEdit->text();
    quint16 port = ui->lineEdit_2->text().toInt();

    // 主动和服务器建立连接
    tcpSocket->connectToHost(QHostAddress(ip), port);
}

widget.cpp


#include <QFileDialog>
#include <QDebug>
#include <QFileInfo>

Widget::Widget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::Widget)
{
    ui->setupUi(this);

    // 监听套接字
    tcpServer = new QTcpServer(this);

    // 监听
    tcpServer->listen(QHostAddress::AnyIPv4, 8888);
    setWindowTitle("服务器 端口8888");

    // 一开始两个按钮都不能按 需要建立连接后才可以按下
    ui->pushButton->setEnabled(false);
    ui->pushButton_2->setEnabled(false);

    // 如果客户端成功和服务器连接
    // tcpServer 会自动触发 newConnection()
    connect(tcpServer, &QTcpServer::newConnection, [=](){
       // 取出建立好连接的套接字
        tcpSocket = tcpServer->nextPendingConnection();
        // 获取对方的ip和端口
        QString ip = tcpSocket->peerAddress().toString();
        quint16 port = tcpSocket->peerPort();

        // qDebug() << port;
        QString temp = QString("[%1:%2]:成功连接").arg(ip).arg(port);
        ui->textEdit->setText(temp);  // 显示到编辑区

        // 成功建立连接后,才可以按钮 选择文件
        ui->pushButton->setEnabled(true);

        connect(tcpSocket, &QTcpSocket::readyRead, [=](){
           // 取客户端的信息
            QByteArray buf = tcpSocket->readAll();
            if(QString(buf) == "file done") // 文件接收完毕
            {
                ui->textEdit->append("客户端反馈:文件发送完毕!!");
                file.close();

                tcpSocket->disconnectFromHost();
                tcpSocket->close();
            }
        });

    });

    connect(&timer,&QTimer::timeout,[=](){
       // 关闭定时器
        timer.stop();

        // 发送文件
        sendData();
    });

}

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

void Widget::sendData()
{
    qint64  len = 0;
    do
    {
        // 每次发送数据的大小
        char buf[4*1024] = {0};
        len  = 0;

        // 往文件中读数据
        len = file.read(buf, sizeof(buf));
        //发送数据,读多少,发多少
        len = tcpSocket->write(buf,len);

        // 发送的数据需要累加
        sendSize += len;
    }while (len > 0) ;

    // 是否发送文件完毕
    if(sendSize == fileSize)
    {
        ui->textEdit->append("文件已发送");
        file.close();

        // 把客户端断开
        // tcpSocket->disconnectFromHost();
        // tcpSocket->close();

        ui->pushButton->setEnabled(false);
        ui->pushButton_2->setEnabled(false);
    }
}

// 选择文件按钮
void Widget::on_pushButton_clicked()
{
    QString filePath = QFileDialog::getOpenFileName(this, "open", "../");
    if(false == filePath.isEmpty())   // 如果选择文件路径有效
    {
        fileName.clear();
        fileSize = 0;

        // 获取文件信息
        QFileInfo info(filePath);
        fileName = info.fileName(); // 获取文件名字
        fileSize = info.size(); // 获取文件大小

        sendSize = 0; // 发送文件的大小

        // 只读方式打开文件
        // 指定文件的名字
        file.setFileName(filePath);

        // 打开文件
        bool isOK = file.open(QIODevice::ReadOnly);
        if(false == isOK)
        {
            qDebug() << "只读方式打开文件失败";
        }

        // 提示打开文件的路径
        ui->textEdit->append(filePath);

        ui->pushButton->setEnabled(false);
        ui->pushButton_2->setEnabled(true);

    }
    else{
        qDebug() << "选择文件路径出错";
    }
}

// 发送文件按钮
void Widget::on_pushButton_2_clicked()
{
    // 先发送文件头信息  文件名##文件大小
    QString head = QString("%1##%2").arg(fileName).arg(fileSize);
    // 发送头部信息
    qint64  len = tcpSocket->write( head.toUtf8() );
    if(len > 0) {   // 头部信息发送成功
        // 发送真正的文件信息
        // 防止TCP黏包问题 需要通过定时器延时 20ms
        timer.start(20);

    }
    else {
        qDebug() << "头部信息发送失败";
        file.close();
        ui->pushButton->setEnabled(true);
        ui->pushButton_2->setEnabled(false);
    }
}

clientwidget.ui

在这里插入图片描述

widget.ui

在这里插入图片描述

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

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

相关文章

九州金榜|导致孩子厌学因素有哪些?家庭教育中要怎样解决?

现在如今孩子出现厌学的情况越来越严重&#xff0c;这也难坏了很多家长&#xff0c;众所周知&#xff0c;当下社会竞争越来越激烈&#xff0c;孩子的压力也越来越大&#xff0c;这也是导致孩子厌学的主要因素。其实家庭因素也是引起孩子厌学情绪产生的重要原因&#xff0c;在家…

通过一篇文章让你了解数据结构和算法的重要性

通过一篇文章让你了解数据结构和算法的重要性 前言一、 什么是数据结构&#xff1f;二、什么是算法&#xff1f;三、数据结构和算法的重要性在校园招聘的笔试中&#xff1a;在校园招聘的面试中&#xff1a;在未来的工作中&#xff1a; 四、如何学好数据结构和算法4.1 死磕代码&…

pom文件写入依赖爆红

pom.xml文件中每次写入依赖后都会爆红&#xff0c;因为单纯引入依赖并没有真正下载依赖包到本地仓库 重载maven项目&#xff0c;检测到没有的依赖后会自动下载依赖包&#xff0c;这时候等待右下角的下载进度条下载完毕即可

swift 长按桌面图标弹出快捷选项

文章目录 一、3D Touch二、主屏交互1. 静态添加2. 动态添加三、监听主屏交互按钮的点击事件四、预览和跳转1. 注册3D touch2. 实现协议3. 在目标控制器复写previewActionItems4. 使用UIContextMenuConfiguration一、3D Touch 3D Touch通过屏幕下方的压力感应器来感知不同的压力…

【InternLM 实战营笔记】基于 InternLM 和 LangChain 搭建MindSpore知识库

InternLM 模型部署 准备环境 拷贝环境 /root/share/install_conda_env_internlm_base.sh InternLM激活环境 conda activate InternLM安装依赖 # 升级pip python -m pip install --upgrade pippip install modelscope1.9.5 pip install transformers4.35.2 pip install str…

PCB Layout完成后,检查注意事项

在PCB Layout完成后&#xff0c;检查注意事项主要包括以下几个方面&#xff1a; 设计规则检查&#xff08;DRC&#xff09;&#xff1a;使用PCB设计软件中的DRC工具&#xff0c;对Layout进行实时检查和发现与预定设计规范不符的设计。这包括元件间距、线宽、线距、过孔大小等是…

继电保护测试仪

武汉凯迪正大继电保护测试仪主要特点 1&#xff0e;满足现场试验要求。本仪器具有标准的四相电压&#xff0c;三相电流输出&#xff0c;既可对传统的各种继电器及保护装置进行试验&#xff0c;也可对现代各种微机保护进行各种试验&#xff0c;特别是对变压器差功保护和备自投装…

一个Web3项目的收官之作,必然是友好的用户界面(Web3项目三实战之四)

正如标题所述,一个对用户体验友好的应用,总是会赢得用户大加赞赏,这是毋庸置疑的。 甭管是web2,亦或是已悄然而至的Web3,能有一个外观优美、用户体验效果佳的的界面,那么,这个应用无疑是个成功的案例。 诚然,Web3项目虽然核心是智能合约攥写,但用户界面也是一个DApp不…

iOS-设置指定边圆角(左上、左下等)

以UILabel举例&#xff0c;效果图如下&#xff1a; 代码如下&#xff1a; //设置左上与右下圆角&#xff08;可自行编辑指定圆角位置&#xff09; UIBezierPath *maskPath [UIBezierPath bezierPathWithRoundedRect:_sleepStateLabel.bounds byRoundingCorners:UIRectCornerT…

c# 获取源码路径与当前程序所在路径

获取源码路径 private static string GetFilePath([CallerFilePath] string path null) {return path;}//当程序所在路径string str67 System.Environment.CurrentDirectory;//源码路径 var path GetFilePath();var directory Path.GetDirectoryName(path);参考

微软开源 SBOM 生成工具:sbom-tool下载及使用详解

github地址 GitHub - microsoft/sbom-tool: The SBOM tool is a highly scalable and enterprise ready tool to create SPDX 2.2 compatible SBOMs for any variety of artifacts.The SBOM tool is a highly scalable and enterprise ready tool to create SPDX 2.2 compatib…

中文分词模拟器【华为OD机试-JAVAPythonC++JS】

题目描述 给定一个连续不包含空格字符串&#xff0c;该字符串仅包含英文小写字母及英文文标点符号(逗号、分号、句号)&#xff0c;同时给定词库&#xff0c;对该字符串进行精确分词。 说明&#xff1a; 1.精确分词&#xff1a; 字符串分词后&#xff0c;不会出现重叠。即“ilov…

ywtool network命令

提示:工具下载链接在文章最后 目录 一.network功能介绍二.配置network功能2.1 network_ip配置检查 2.2 network_br配置2.2.1 配置的网桥原先不存在检查2.2.2 配置的网桥已存在-修改网桥IP检查2.2.3 配置的网桥已存在-只添加网卡到网桥里检查 2.3 network_bond配置检查 2.4 netw…

金仕达与 DolphinDB 建立深度合作,共筑 FICC 科技创新新篇章

从“关起门做交易”到“打开门做服务”&#xff0c;国内 FICC 业务正经历从自营到市场化服务的转变&#xff0c;借助数据分析、算法交易等技术的快速发展&#xff0c;交易团队能够更加主动地发现市场需求&#xff0c;为不同客群提供更好的做市业务&#xff0c;FICC 交易电子化已…

基于Python3的数据结构与算法 - 07 归并排序

一、归并 引入 假设现在的列表分两段有序&#xff0c;如何将其合并成为一个有序列表。 这种操作成为一次归并。 归并的思路 分别对两个列表进行遍历&#xff0c;比较两个列表中的最小值&#xff0c;将更小的取出来。取出后一次进行上操作&#xff0c;直到其中一个列表中的元…

web自动化笔记六:弹出框处理

1、弹出框类型&#xff1a; 1)、alert 警告框 2)、confirm 确认框 3)、prompt 提示框 2、弹出框处理方法&#xff08;方法三种弹出框操作都一样&#xff09; 1)、获取弹出框对象&#xff1a; alert driver.switch_to.ale…

笔记72:关于IMU(惯性测量单元)传感器的作用【不涉及公式推导】

一、IMU传感器是什么&#xff1a; 惯性测量单元IMU&#xff08;Inertial Measurement Unit&#xff09;是一种使用【加速度计】和【陀螺仪】来测量【物体三轴姿态角&#xff08;空间姿态&#xff09;】的装置&#xff1b;IMU在坐标系的每个坐标轴上&#xff0c;均安装有1个陀螺…

Unity(第十八部)物理力学,碰撞,触发、关节和材质

1、重力 刚体组件 英文中文描述RigidBody刚体组件physics->rigidbody &#xff0c;刚体组件使一个物体有了质量&#xff0c;重力等。&#xff0c;use gravity 勾选后&#xff0c;物体才会受到重力&#xff0c;会自动下落&#xff0c;取消勾选就不会。&#xff0c;&#xf…

初学JavaScript总结

0 JavaScript html完成了架子&#xff0c;css做了美化&#xff0c;但是网页是死的&#xff0c;需要给他注入灵魂&#xff0c;所以接下来需要学习JavaScript&#xff0c;这门语言会让页面能够和用户进行交互。JavaScript又称为脚本语言&#xff0c;可以通过脚本实现用户和页面的…

1.1为什么需要对数值类型的特征做归一化?

01 知识点&#xff1a;特征归一化&#xff08;第一章 特征工程&#xff09; 摘要&#xff1a; 为什么需要对数值类型的特征做归一化&#xff1f; 简要回答&#xff1a;对数值类型的特征做归一化&#xff0c;使得各指标除以同一个数量级&#xff0c;以便进行分析。 场景描述 为…