Qt实现XYModem协议(五)

news/2024/5/19 10:30:57

1 概述

  XMODEM协议是一种使用拨号调制解调器的个人计算机通信中广泛使用的异步文件运输协议。这种协议以128字节块的形式传输数据,并且每个块都使用一个校验和过程来进行错误检测。使用循环冗余校验的与XMODEM相应的一种协议称为XMODEM-CRC。还有一种是XMODEM-1K,它以1024字节一块来传输数据。YMODEM也是一种XMODEM的实现。它包括XMODEM-1K的所有特征,另外在一次单一会话期间为发送一组文件,增加了批处理文件传输模式。

本文利用C++实现XYModem-1K协议,并利用Qt串口类QSerialPort实现数据读写。

3 实现

3.4 XYModemSendFile

该模块实现XYModem协议发送文件。

流程图:
流程图

3.4.1 XYModemSendFile定义

class QSerialPort;
class XYModemSendFile : public QObject, public YModem
{Q_OBJECT
public:explicit XYModemSendFile(QSerialPort *serial, QObject *parent = nullptr);public slots:void startYModem(QString const& fileName);void startXModem(QString const& fileName);void stop() { { doSignal(); }}void cancel() { tx_cancle(); }
signals:void gotFileSize(quint64 filesize);void progressInfo(quint32 blockNumber, quint64 bytesOfSend);void error(QString const& e);void finished();protected:uint32_t write(uint8_t const *data, uint32_t size) override;uint32_t read(uint8_t *data, uint32_t size) override;uint8_t get_code(bool isWait = true) override;
private:bool singled() { return signal_; }void doSignal() { signal_ = true; };void doError(QString const& text);
private:QSerialPort* serial_;volatile bool signal_;
};

公共接口:

  • startYModem 开始YModem协议发送文件
  • startXModem 开始XModem协议发送文件
  • stop 停止发送
  • cancel 取消发送

信号:

  • gotFileSize 文件大小信号
  • progressInfo 传输进度信号
  • error 出错信号
  • finished 传输结束信号

重载接口:

  • write 向串口写数据
  • read 从串口读取数据
  • get_code 读取操作码

3.4.2 XYModemSendFile实现

3.4.2.1 startYModem
void XYModemSendFile::startYModem(QString const& fileName)
{QFileInfo fileInfo(fileName);uint64_t fileSize = fileInfo.size();std::string filename = fileInfo.fileName().toStdString();std::string filesize = QString::number(fileSize).toStdString();if(filename.size() + filesize.size() + 2 > SIZE1){doError("Filename too long!");return;}//Get Start flagif(get_code() != C){doError("Can not get  C!");return;}//SOH first blockemit gotFileSize(fileSize);if(!tx_start(filename, filesize)){doError("Can not get  ACK and C!");return;}//Send data of fileQFile file(fileName);if(!file.open(QIODevice::ReadOnly)){doError(QString("%1 cannot be opened!").arg(fileName));return;}uint8_t data[SIZE2];quint64 bytesOfSend = 0;quint32 block = 0;bool is_end = false;while(!singled()){quint64 size = file.read((char *)data, sizeof(data));if(size == 0){is_end = true;break;}if(tx_send(data, size)){block++;bytesOfSend += size;emit progressInfo(block, bytesOfSend);}else{emit error("send is error");break;}}//Send endif(is_end){if(tx_eot()){if(tx_end()){//std::cout << "end is ok" << std::endl;}}}emit finished();serial_->moveToThread(QApplication::instance()->thread());
}

函数流程:

  • 获取文件名和文件大小字符串
  • 如果文件名和文件大小字符串大小大于Size1(128)则返回文件名称太长错误返回
  • 获取操作码
  • 获得非C操作码,失败返回
  • 发送文件大小信号gotFileSize
  • 发送开始包(包括文件名称和文件大小。YModem协议发送该包,XModem协议不发送该包)
  • 打开文件,如果失败则返回
  • 读取文件内容
  • 发送文件内容
  • 发送成功发送,发送进度信号progressInfo
  • 发送失败,则发送错误信号并返回
  • 重复上述4步,直到文件发送完毕或停止
  • 如果文件发送完毕包(tx_eot),发送文件结束标志
  • 发送通信结束包(tx_end),结束通信。(这里只发送一个文件所以发送tx_end, 如果是多个文件需要发送tx_start开始新文件发送)
  • 发送传输结束信号finished
3.4.2.2 startXModem
void XYModemSendFile::startXModem(QString const& fileName)
{QFileInfo fileInfo(fileName);uint64_t fileSize = fileInfo.size();//Get Start flagif(get_code() != C){doError("Can not get  C!");return;}//SOH first blockemit gotFileSize(fileSize);//Send data of fileQFile file(fileName);if(!file.open(QIODevice::ReadOnly)){doError(QString("%1 cannot be opened!").arg(fileName));return;}uint8_t data[SIZE2];quint64 bytesOfSend = 0;quint32 block = 0;bool is_end = false;next_id();while(!singled()){quint64 size = file.read((char *)data, sizeof(data));if(size == 0){is_end = true;break;}if(tx_send(data, size)){block++;bytesOfSend += size;emit progressInfo(block, bytesOfSend);}else{emit error("send is error");break;}}//Send endif(is_end){if(tx_eot()){//std::cout << "end is ok" << std::endl;}}emit finished();serial_->moveToThread(QApplication::instance()->thread());
}

函数流程:

  • 获取文件大小
  • 获取操作码
  • 如果不是C码,失败返回
  • 发送文件大小信号gotFileSize
  • 打开文件,如果失败则返回
  • 发送文件内容
  • 发送成功发送,发送进度信号progressInfo
  • 发送失败,则发送错误信号并返回
  • 重复上述4步,直到文件发送完毕或停止
  • 如果文件发送完毕包(tx_eot),发送文件结束标志
  • 发送传输结束信号finished
3.4.2.3 write/read
uint32_t XYModemSendFile::write(uint8_t const *data, uint32_t size)
{return serial_->write((const char *)data, size);
}
uint32_t XYModemSendFile::read(uint8_t *data, uint32_t size)
{return serial_->read((char *)data, size);
}

函数说明:

  • 直接调用串口读写接口实现读写接口。
3.4.2.4 get_code
uint8_t XYModemSendFile::get_code(bool isWait)
{while(!singled()){if(serial_->waitForReadyRead(10)){uint8_t data[1] = { 0 };read(data, sizeof(data));return data[0];}if(!isWait)break;}return MAX;
}

函数流程:

  • 等待串口输入
  • 如果有输入则读取一字节做为code码并返回.
  • 如果一直没有输入直到调用stop后返回无效码MAX.
3.4.2.5 doError
void XYModemSendFile::doError(QString const& text)
{emit error(text);serial_->moveToThread(QApplication::instance()->thread());emit finished();
}

函数流程:

  • 发送错误信号
  • 发送结束信号

Qt实现XYModem协议(四) Qt实现XYModem协议(六)


http://www.mrgr.cn/p/67511786

相关文章

【软考经验分享】软考-中级-嵌入式备考

这里写目录标题 教辅用书嵌入式系统设计师考试大纲嵌入式系统设计师教程嵌入式系统设计师5天修炼嵌入式系统设计师考前冲刺100题 刷题软件希赛网软考真题 视频教程希赛网王道-计组计网 教辅用书 嵌入式系统设计师考试大纲 50页左右&#xff0c;内容为罗列一些考点&#xff0c…

构建安全高效的前端权限控制系统

✨✨谢谢大家捧场&#xff0c;祝屏幕前的小伙伴们每天都有好运相伴左右&#xff0c;一定要天天开心哦&#xff01;✨✨ &#x1f388;&#x1f388;作者主页&#xff1a; 喔的嘛呀&#x1f388;&#x1f388; ✨✨ 帅哥美女们&#xff0c;我们共同加油&#xff01;一起进步&am…

学习Rust的第11天:模块系统

Rust的模块系统可以使用它来管理不断增长的项目&#xff0c;并跟踪 modules 存储在何处。 Rust的模块系统是将代码组织成逻辑片段的有效工具&#xff0c;因此可以实现代码维护和重用。模块支持分层组织、隐私管理和代码封装。Rust为开发人员提供了多功能和可扩展的方法来管理项…

Docker in Docker的原理与实战

Docker in Docker&#xff08;简称DinD&#xff09;是一种在Docker容器内部运行另一个Docker实例的技术。这种技术允许用户在一个隔离的Docker容器中创建、管理和运行其他Docker容器&#xff0c;从而提供了更灵活和可控的部署选项。以下是DinD的主要特点&#xff1a; 隔离性&am…

element plus:tree拖动节点交换位置和改变层级

图层list里有各种组件&#xff0c;用element plus的tree来渲染&#xff0c;可以把图片等组件到面板里&#xff0c;面板是容器&#xff0c;非容器组件&#xff0c;比如图片、文本等&#xff0c;就不能让其他组件拖进来。 主要在于allow-drop属性的回调函数编写&#xff0c;要理清…

Linux2.6内核进程调度队列

目录 运行队列runqueue 活跃队列&过期队列 queue[140]&优先级&队列数组下标 bitmap[5]&O(1)调度算法 nr_active active指针和expired指针 O(1)调度算法之调度过程 本篇是Linux进程概念篇的最后一篇&#xff0c;Linux2.6内核是一个具体的/可行的/实际的存…

深入理解Linux文件系统和日志分析

目录 一.inode与block 1.inode与block概述 1.1.文件数据包括元信息与实际数据 1.2.文件存储在硬盘上&#xff0c;硬盘最小存储单位是“扇区”&#xff0c;每个扇区存储512字节 1.3.block&#xff08;块&#xff09; 1.4.inode&#xff08;索引节点&#xff09; 2.inode内…

军工单位安全内网文件导出,怎样做到严密的安全管控?

军工单位是指承担国家下达的军事装备、产品研制、生产计划任务的企、事业单位,主要包括电子工业部、航空工业总公司、航天工业总公司、兵器工业总公司、核工业总公司、船舶工业总公司、中国工程物理研究院及各省国防工业办公室等。 军工单位的特点主要体现在以下几个方面: 承…

Vue3中使用无缝滚动插件vue3-seamless-scroll

官网&#xff1a;https://www.npmjs.com/package/vue-seamless-scroll 1、实现效果文字描述&#xff1a; 表格中的列数据进行横向无缝滚动&#xff0c;某一列进行筛选的时候&#xff0c;重新请求后端的数据&#xff0c;进行刷新 2、安装&#xff1a;npm i vue3-seamless-scrol…

Keil和VSCode协同开发STM32程序

系列文章 STM32单片机系列专栏 C语言术语和结构总结专栏 文章目录 1. 配置环境 2. 测试打开工程 3. 测试编译工程 随着项目的复杂度上升&#xff0c;开发者不仅需要强大的硬件支持&#xff0c;还需要一个高效和灵活的开发环境。 vscode是一款集成大量可以便携开发插件的代码…

爬虫js逆向(python调用js学习)

首先介绍pyexecjs的使用 PyExecJs 是一个python 库,用于在 Python 环境中执行javaScript代码。它实际上是对 Execs 库的 Python 封装,Execls 本身是一个通用的 JavaScript 运行环境的抽象层。使用PyExecJs,你可以在Python 中执行JavaScript代码,而无需启动一个完整的JavaSc…

维基百科、百度百科和搜狗百科词条的创建流程

随着网络的发展&#xff0c;百度百科、搜狗百科、维基百科等百科网站已经成为大众获取知识的重要途径。因为百科具有得天独厚的平台优势&#xff0c;百科上的信息可信度高&#xff0c;权威性强。所以百科平台也成为商家的必争之地。这里小马识途聊聊如何创建百度百科、搜狗百科…

贪吃蛇(C语言版)

在我们学习完C语言 和单链表知识点后 我们开始写个贪吃蛇的代码 目标&#xff1a;使用C语言在Windows环境的控制台模拟实现经典小游戏贪吃蛇 贪吃蛇代码实现的基本功能&#xff1a; 地图的绘制 蛇、食物的创建 蛇的状态&#xff08;正常 撞墙 撞到自己 正常退出&#xf…

智能组网怎么样?

智能组网技术的出现&#xff0c;使得网络连接更加便捷和智能化。无论我们身处何地&#xff0c;只要有网络覆盖&#xff0c;就能轻松进行远程连接和访问。智能组网到底如何实现的呢&#xff1f;本文将就智能组网的优势进行探讨&#xff0c;以便更好地了解其特点和应用场景。 【天…

idle的下载和环境配置(python)

1.进入官网:https://www.python.org/ 2.downloads->windows选择对应版本(这里我选择3.10.0是因为听说10比较稳定) 3. 找到刚下载的Python程序安装包,双击打开,运行安装程序。 直接点击下一步,直至安装成功,点击完成就可以了。如果想切换安装目录,可以在那一步换一下安…

自己手动在Linux上实现一个简易的端口扫描器

背景 常常听到网络攻击有一个东西叫做端口扫描器&#xff0c;可以扫描指定服务器开放的端口&#xff0c;然后尝试连接&#xff0c;并寻找漏洞&#xff0c;最终攻破服务器。而那些使用的端口扫描器都是一个个现成的程序&#xff0c;看上去很厉害的样子。而实际上这些东西对于懂…

[dp 小计] SOSdp

复健 SOSdp(sum over subsets dynamic programming)。 引入 令 \(F(x)=\sum\limits_{u\subseteq x} A(u)\) 其中 \(A\) 为给定数组,求出 \(\forall x, F(x)\) 。 思路一 暴力枚举子集,时间复杂度 \(O(4^n)\)。 思路二 优化子集枚举,时间复杂度 \(O(3^n)\)。 思路三 考虑 SOS…

HTTP慢连接攻击的原理和防范措施

随着互联网的快速发展&#xff0c;网络安全问题日益凸显&#xff0c;网络攻击事件频繁发生。其中&#xff0c;HTTP慢速攻击作为一种隐蔽且高效的攻击方式&#xff0c;近年来逐渐出现的越来越多。 为了防范这些网络攻击&#xff0c;我们需要先了解这些攻击情况&#xff0c;这样…

Redis篇:缓存击穿及解决方案

1.何为缓存击穿 缓存击穿问题也叫热点Key问题&#xff0c;就是一个被高并发访问并且缓存重建业务较复杂的key突然失效了&#xff08;有可能是正好过期了&#xff09;&#xff0c;无数的请求访问会在瞬间给数据库带来巨大的冲击。 常见的解决方案有两种&#xff1a; 互斥锁 逻…

【深度学习】yolo-World,数据标注,zeroshot,目标检测

仓库&#xff1a;https://github.com/AILab-CVC/YOLO-World 下载权重&#xff1a; 仓库下载和环境设置 下载仓库&#xff1a;使用以下命令从 GitHub 上克隆仓库&#xff1a; git clone --recursive https://github.com/AILab-CVC/YOLO-World.git创建并激活环境&#xff1a…