Qt实现XYModem协议(一)

1 概述

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

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

2 概要设计

2.1 类图

类图

类型说明:

  • Modem XYModem协议基类,实现CRC16校验,并定义读写接口。
  • XModem 实现XModem协议。
  • YModem 实现YModem协议。
  • XYModemSendFile 实现XYModem协议发送文件。
  • XYModemRecvFile 实现XYModem协议接收文件。
  • XYModemFileSender 实现在线程中异步发送文件。
  • XYModemFileRecver 实现在线程中异步接收文件。

2.2 模块

整个代码分为7个模块.

2.2.1 Modem

该模块定义和实现了Modem类型。

Modem类型是纯虚类型,其派生类需要实现下面两个虚函数:

  • write 写数据接口
  • read 读数据接口

文件列表:

  • modem.h
  • modem.cpp

2.2.2 XModem

该模块定义和实现了XModem类型。

XModem类型实现了XModem协议,定义了纯虚接口:

  • get_code 获取操作码Code

并定义了如下接口:

  • tx_send 发送数据
  • tx_eot 判断发送是否结束。
  • tx_code 发送操作码
  • wait_start 发送等待接收码
  • tx_cancel 发送取消包
  • not_id id的反码
  • next_id 下一ID

文件列表:

  • xmodem.h
  • xmodem.cpp

2.2.3 YModem

该模块定义和实现了YModem类型。

YModem类型在XModem基础上实现了YModem协议,定义接口:

  • tx_start 开始文件发送
  • tx_end 判断是否是最后一个包

文件列表:

  • ymodem.h
  • ymodem.cpp

2.2.4 XYModemSendFile

该模块定义和实现了XYModemSendFile类型。

XYModemSendFile类型实现XYModem协议文件发送,接口如下:

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

实现如下接口:

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

文件列表:

  • xmodemsendfile.h
  • xmodemsendfile.cpp

2.2.5 XYModemRecvFile

该模块定义和实现了XYModemRecvFile类型。

XYModemRecvFile类型实现XYModem协议文件接收,接口如下:

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

实现如下接口:

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

文件列表:

  • xmodemrecvfile.h
  • xmodemrecvfile.cpp

2.2.6 XYModemFileSender

该模块定义和实现了XYModemFileSender类型。

XYModemSendFile发送文件是同步操作,XYModemFileSender将发送文件操作放入线程中实现异步调用。

文件列表:

  • xymodemfilesender.h
  • xymodemfilesender.cpp

2.2.7 XYModemFileRecver

该模块定义和实现了XYModemFileRecver类型。

XYModemFileRecver发送文件是同步操作,XYModemFileRecver将接收文件操作放入线程中实现异步调用。

文件列表:

  • xymodemfilerecver.h
  • xymodemfilerecver.cpp

使用

发送文件

void SerialPortWidget::sendFileByXYModem(QString const& fileName, bool isYModem)
{
    QObject::disconnect(serial, SIGNAL(readyRead()), this, SLOT(onData()));

    FileProgressDialog dialog(this);
    XYModemFileSender sender(serial, isYModem);

    connect(&sender, &XYModemFileSender::gotFileSize, &dialog, &FileProgressDialog::setFileSize);
    connect(&sender, &XYModemFileSender::progressInfo, &dialog, &FileProgressDialog::setProgressInfo);
    connect(&sender, &XYModemFileSender::finished, &dialog, &FileProgressDialog::finished);
    connect(&sender, &XYModemFileSender::error, &dialog, &FileProgressDialog::error);

    if(isYModem)
    {
        dialog.setTitle(tr("YMODEM Send"));
        dialog.setProtocol(tr("1K YMODEM"));
    }
    else
    {
        dialog.setTitle(tr("XMODEM Send"));
        dialog.setProtocol(tr("1K XMODEM"));
    }
    dialog.setFilename(QFileInfo(fileName).fileName());
    dialog.setModal(true);
    dialog.setVisible(true);

    sender.start(fileName);
    while(!dialog.isFinished())
    {
        if(dialog.isCancel())
        {
            sender.stop();
            while(!dialog.isFinished())
                QApplication::processEvents();
            sender.cancel();
        }
        QApplication::processEvents();
    }

    connect(serial, SIGNAL(readyRead()), this, SLOT(onData()));
}

接收文件

void SerialPortWidget::recvFileByXYModem(QString const& fileName, bool isYModem)
{
    QObject::disconnect(serial, SIGNAL(readyRead()), this, SLOT(onData()));
    FileProgressDialog dialog(this);
    XYModemFileRecver recver(serial, isYModem);
    connect(&recver, &XYModemFileRecver::gotFileSize, &dialog, &FileProgressDialog::setFileSize);
    connect(&recver, &XYModemFileRecver::progressInfo, &dialog, &FileProgressDialog::setProgressInfo);
    connect(&recver, &XYModemFileRecver::finished, &dialog, &FileProgressDialog::finished);
    connect(&recver, &XYModemFileRecver::error, &dialog, &FileProgressDialog::error);

    if(isYModem)
    {
        dialog.setTitle(tr("YMODEM Recv"));
        dialog.setProtocol(tr("1K YMODEM"));
    }
    else
    {
        dialog.setTitle(tr("XMODEM Recv"));
        dialog.setProtocol(tr("1K XMODEM"));
    }

    dialog.setFilename(QFileInfo(fileName).fileName());
    dialog.setModal(true);
    dialog.setVisible(true);

    recver.start(fileName);
    while(!dialog.isFinished())
    {
        if(dialog.isCancel())
        {
            recver.stop();
            while(!dialog.isFinished())
                QApplication::processEvents();
            recver.cancel();
        }
        QApplication::processEvents();
    }

    connect(serial, SIGNAL(readyRead()), this, SLOT(onData()));
}

Qt实现XYModem协议(二)

  • 68
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

flysnow010

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值