【翻译】带CRC校验的XModem协议

本文介绍了Xmodem协议的工作原理及其实现细节。Xmodem作为一种半双工通讯协议,利用CRC校验来保证数据传输的准确性。文章详细阐述了Xmodem的数据包结构、同步方法及接收端注意事项。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

导论

Xmodem协议是一种很久之前就被提出的协议,其作为一种简单的工具,使得两台电脑可以相互通讯。由于其具有的半双工、128字节长度包数据(译者注:对于包数据长度不足128字节的情况,使用0x1A填充到128字节,一般发生于传输的最后一个数据包)、ACK/NACK应答以及CRC校验这些机制,在很多应用场合中都能见到Xmodem协议的身影。实际上,现在个人计算机上的大多数通信包都有一个xmodem协议可供用户使用。

工作原理

Xmodem是一种半双工的通讯协议。每当接收者接收到一个数据包,其将会选择应答(ACK)或者不应答(NAK)这个数据包。与其他常见的通讯协议一样,更加稳健的16位CRC校验被用于校验Xmodem传输的数据的有效性(译者注:并不是所有的Xmodem协议都使用CRC校验,更老的版本使用的是简单的8位累加和校验,在90年代修订了一次标准,改为了16位CRC校验)。Xmodem可以看作是一种由接收端驱动的协议。也就是说,接收端发送一个初始化字符’C’到发送端来告知已经准备好以CRC校验的方式接收数据。之后,发送端会发送一个133字节的数据包,接收端校验收到的数据包并且回应一个应答(ACK)或者非应答(NAK),根据接收端的应答,发送端会决定发送下一个数据包还是重新发送上一次的数据包。这个过程会一直进行,直到接收端收到EOT之后发送一个ACK到发送端。在进行握手之后,接收端通过回应ACK或NAK到发送端来控制数据流的传输。

表1:XmodemCRC数据包结构

 

符号定义

以下符号定义被用于协议的流控制。

XmodemCRC数据包的字节1的值只能是SOH、EOT、CAN或者ETB中的一个,除此之外的任何值都应当被视为一个错误。字节2和字节3组成带校验和(checksum)功能的包序号,这两位相加起来应该永远等于0xFF。请记住,包序号从1开始,并且在大于255个数据包需要接收时溢出为0。字节4到字节131组成数据部分,它们可以是任意数据。字节132和133组成了16位CRC校验。CRC的高位为字节132。CRC校验只计算了数据部分,即字节4到字节131。

同步方法

接收端通过发送ASCII码表中的字符’C’(0x43)到发送端来指明希望通过CRC方法来进行数据校验。在发送初始字符’C’之后,接收端等待3秒钟直到等待超时或者缓冲区满标志位被置位。如果接收端等待超时了,另一个’C’会被发送给发送端并且再次进行一次时长3秒的等待。这个流程会一直进行直到接收端收到了一个完整的133字节的数据包。

接收端注意事项

在以下情况下,接收端应该回应非应答(NAK):

  1. 任何字节出现帧错误
  2. 任何字节出现溢出错误
  3. 收到重复序号的包
  4. CRC校验错误
  5. 接收超时(未在1秒钟内接收完一个数据包)

对于任何非应答(NAK),发送端将会重发上一次的数据包。情况1和情况2应该被认为是严重的硬件错误。确保发送端和接收端使用同样的波特率、开始位和停止位。情况3通常发生于发送端收到的应答(ACK)发生了混淆,于是发送端重发了上一次的数据包。情况4会在存在干扰的环境下出现,这个问题应该会在接收端非应答(NAK)发送端后被纠正(译者注:即发送端会重发校验不对的数据包)。

收发示例

简易的CRC校验计算代码

int calcrc(char *ptr, int count)
{
    int crc;
    char i;
    crc = 0;
    while (--count >= 0)
    {
        crc = crc ^ (int)*ptr++ << 8;
        i = 8;
        do
        {
            if (crc & 0x8000)
                crc = crc << 1 ^ 0x1021;
            else
                crc = crc << 1;
        } while (--i);
    }
    return (crc);
}

 

### XMODEM 协议中的 CRC 校验 #### 实现细节 XMODEM协议使用循环冗余校验CRC)作为错误检测机制之一。对于16位CRC校验,其多项式通常设置为`0x1021`[^5]。 在具体实现上,可以参考如下C#代码片段用于计算CRC-16/XMODEM: ```csharp public static int CRC_XModem(byte[] bytes) { int crc = 0x00; // 初始值设为0x00 const int polynomial = 0x1021; foreach (byte b in bytes){ for(int i = 0 ;i<8;i++){ bool bit = ((b >> (7-i))&1)==1; bool c15=((crc>>15)&1)==1; crc<<=1; if(c15^bit)crc^=polynomial; } } return crc & 0xFFFF; } ``` 这段函数接收一个字节数组并返回对应的CRC值。通过逐位处理输入的数据流并与预定义的生成多项式相异或操作来更新CRC寄存器的内容直到完成整个消息序列的扫描为止。 当发送方准备传送文件时,会先按照上述方法计算待传数据块的CRC值,并将其附加于实际有效载荷之后一同发出;接收端则会在接收到完整的帧后独立执行相同的CRC运算过程并将结果与随包附的那个进行对比验证——只有两者完全一致才认为此次通信无误发生,反之则触发重发请求或其他纠错措施[^3]。 #### 应用场景 为了提高传输效率,在某些变种版本比如1K-Xmodem里边,除了保持原有特性外还将每次交换的最大单位扩大到了1KB大小的同时调整了起始标志符以便区分不同类型的分组结构从而进一步优化整体性能表现。 另外值得注意的一点是在早期实践中为了避免兼容性问题,“基本”的XMODEM选项往往被单独列出供用户选择而不默认开启更高级别的功能如支持-CRC模式尽管后者理论上能够提供更好的可靠性保障[^1]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值