1 概述
XMODEM协议是一种使用拨号调制解调器的个人计算机通信中广泛使用的异步文件运输协议。这种协议以128字节块的形式传输数据,并且每个块都使用一个校验和过程来进行错误检测。使用循环冗余校验的与XMODEM相应的一种协议称为XMODEM-CRC。还有一种是XMODEM-1K,它以1024字节一块来传输数据。YMODEM也是一种XMODEM的实现。它包括XMODEM-1K的所有特征,另外在一次单一会话期间为发送一组文件,增加了批处理文件传输模式。
本文利用C++实现XYModem-1K协议,并利用Qt串口类QSerialPort实现数据读写。
3 实现
3.7 XYModemFileRecver
该模块实现XYModem协议在线程中异步接收文件。
3.7.1 XYModemFileRecver定义
class QSerialPort;
class XYModemRecvFile;
class XYModemFileRecver : public QObject
{
Q_OBJECT
public:
explicit XYModemFileRecver(QSerialPort *serial, bool isYModem = true,
QObject *parent = nullptr);
~XYModemFileRecver();
signals:
void start_recv(QString const& fileName);
void stop_recv();
void cancel_recv();
void gotFileSize(quint64 filesize);
void progressInfo(quint32 blockNumber, quint64 bytesOfSend);
void finished();
void error(QString const& e);
public:
void start(QString const& fileName);
void stop();
void cancel();
private:
QThread workerThread;
XYModemRecvFile* worker;
};
公共接口:
- 开始XYModem协议接收文件
- startXModem 开始XModem协议接收文件
- stop 停止接收
- cancel 取消接收
信号:
- gotFileSize 文件大小信号
- progressInfo 传输进度信号
- error 出错信号
- finished 传输结束信号
重载接口:
- write 向串口写数据
- read 从串口读取数据
- get_code 读取操作码
- do_recv 接收数据并验证
3.7.2 XYModemRecvFile实现
3.7.2.1 构造函数/析构函数
XYModemFileRecver::XYModemFileRecver(QSerialPort *serial, bool isYModem, QObject *parent)
: QObject(parent)
{
worker = new XYModemRecvFile(serial);
serial->moveToThread(&workerThread);
worker->moveToThread(&workerThread);
connect(&workerThread, &QThread::finished, worker, &QObject::deleteLater);
if(isYModem)
connect(this, &XYModemFileRecver::start_recv, worker, &XYModemRecvFile::startYModem);
else
connect(this, &XYModemFileRecver::start_recv, worker, &XYModemRecvFile::startXModem);
connect(this, &XYModemFileRecver::stop_recv, worker, &XYModemRecvFile::stop);
connect(this, &XYModemFileRecver::cancel_recv, worker, &XYModemRecvFile::cancel);
connect(worker, &XYModemRecvFile::gotFileSize, this, &XYModemFileRecver::gotFileSize);
connect(worker, &XYModemRecvFile::progressInfo, this, &XYModemFileRecver::progressInfo);
connect(worker, &XYModemRecvFile::finished, this, &XYModemFileRecver::finished);
connect(worker, &XYModemRecvFile::error, this, &XYModemFileRecver::error);
workerThread.start();
}
XYModemFileRecver::~XYModemFileRecver()
{
workerThread.quit();
workerThread.wait();
}
函数说明:
- 构造函数
- 将serial和worker移动到workerThread线程
- 连接信号和槽函数,如果YModem,start_recv连接startYModem,否则连接startXModem
- 启动线程
- 析构函数
- 退出线程
- 等待线程退出
3.7.2.2 start/stop/cancel
void XYModemFileRecver::start(QString const& fileName)
{
emit start_recv(fileName);
}
void XYModemFileRecver::stop()
{
worker->stop();
}
void XYModemFileRecver::cancel()
{
worker->cancel();
}
函数说明:
- start 发送信号start_send开始文件传输
- stop 调用work函数stop停止操作
- cancel 发送信号cancel_send取消文件传输操作
Qt实现XYModem协议(七)