了解ZMODEM协议

Jef*_*f E 11 protocols zmodem

我需要在我的程序中包含基本的文件发送和文件接收例程,它需要通过ZMODEM协议.问题是我无法理解规范.

作为参考,这是规范.

规范没有定义各种常量,所以这里是来自Google的头文件.

在我看来,在该文档中有许多重要的事情未定义:

  • 它经常引用ZDLE编码,但它是什么?我什么时候使用它,什么时候不使用它?
  • 在ZFILE数据帧之后,传输文件的元数据(文件名,修改日期,大小等).接下来是ZCRCW块,然后是根据规范未定义类型的块.据称ZCRCW块包含一个16位CRC,但规范没有定义CRC计算的数据.
  • 它没有定义它使用的CRC多项式.我偶然发现CRC32 poly是标准的CRC32,但我对CRC16 poly没有这么好的运气.没关系,我通过反复试验找到了它.CRC16多晶硅是0x1021.

我环顾四周寻找参考代码,但我能找到的是从90年代早期开始的无法读取的无证件C文件.我也从MSDN中找到了这组文件,但它与我运行的测试有点模糊和矛盾:http://msdn.microsoft.com/en-us/library/ms817878.aspx(你可能需要通过谷歌的缓存查看)

为了说明我的困难,这是一个简单的例子.我在服务器上创建了一个包含"Hello world!"的纯文本文件,它名为helloworld.txt.

我使用以下命令从服务器启动传输:

sx --zmodem helloworld.txt
Run Code Online (Sandbox Code Playgroud)

这会提示服务器发送以下ZRQINIT帧:

2A 2A 18 42 30 30 30 30 30 30 30 30 30 30 30 30   **.B000000000000
30 30 0D 8A 11                                    00.Š.
Run Code Online (Sandbox Code Playgroud)

这有三个问题:

  • 填充字节(0x2A)是否是任意的?为什么这里有两个,但在其他情况下只有一个,有时没有?
  • 该规范最后没有提到[CR] [LF] [XON],但是MSDN文章的确如此.为什么会这样?
  • 为什么[LF]设置了位0x80?

在此之后,客户端需要发送ZRINIT帧.我从MSDN文章中得到了这个:

2A 2A 18 42 30 31 30 30 30 30 30 30 32 33 62 65   **.B0100000023be
35 30 0D 8A                                       50.Š
Run Code Online (Sandbox Code Playgroud)

除了[LF] 0x80标志问题,我还有两个问题:

  • 这次为什么不包括[XON]?
  • CRC是根据二进制数据还是ASCII十六进制数据计算的?如果它在二进制数据上,我得到0x197C,如果它在ASCII十六进制数据上,我得到0xF775; 这些都不是帧中的实际内容(0xBE50).(已解决;它遵循您使用的任何模式.如果您处于BIN或BIN32模式,则它是二进制数据的CRC.如果您处于ASCII十六进制模式,则它是由ASCII十六进制字符表示的CRC的CRC .)

服务器以ZFILE帧响应:

2A 18 43 04 00 00 00 00 DD 51 A2 33               *.C.....ÝQ¢3
Run Code Online (Sandbox Code Playgroud)

好.这个是有道理的.如果我计算[04 00 00 00 00]的CRC32,我确实得到0x33A251DD.但是现在我们最后没有[CR] [LF] [XON].为什么是这样?

在此帧之后,服务器也会立即发送文件的元数据:

68 65 6C 6C 6F 77 6F 72 6C 64 2E 74 78 74 00 31   helloworld.txt.1
33 20 32 34 30 20 31 30 30 36 34 34 20 30 20 31   3 240 100644 0 1
20 31 33 00 18 6B 18 50 D3 0F F1 11                13..k.PÓ.ñ.
Run Code Online (Sandbox Code Playgroud)

这甚至没有标题,只是直接跳转到数据.好的,我可以忍受.然而:

  • 我们有第一个神秘的ZCRCW框架:[18 6B].这个框架有多长?CRC数据在哪里,是CRC16还是CRC32?它没有在规范中的任何地方定义.
  • MSDN文章规定[18 6B]后面跟[00],但事实并非如此.
  • 然后我们有一个未定义类型的帧:[18 50 D3 0F F1 11].这是一个单独的框架还是ZCRCW的一部分?

客户端需要使用ZRPOS帧进行响应,再次从MSDN文章中获取:

2A 2A 18 42 30 39 30 30 30 30 30 30 30 30 61 38   **.B0900000000a8
37 63 0D 8A                                       7c.Š
Run Code Online (Sandbox Code Playgroud)

与ZRINIT帧相同的问题:CRC错误,[LF]设置了位0x80,并且没有[XON].

服务器以ZDATA帧响应:

2A 18 43 0A 00 00 00 00 BC EF 92 8C               *.C.....¼ï’Œ
Run Code Online (Sandbox Code Playgroud)

与ZFILE相同的问题:CRC都很好,但是[CR] [LF] [XON]在哪里?

在此之后,服务器发送文件的有效负载.由于这是一个简短的例子,它适合一个块(最大大小为1024):

48 65 6C 6C 6F 20 77 6F 72 6C 64 21 0A            Hello world!.
Run Code Online (Sandbox Code Playgroud)

从文章中提到的内容来看,有效负载是通过[ZDLE]进行转义的.那么如何传输恰好匹配[ZDLE]值的有效载荷字节?还有这样的其他价值吗?

服务器以这些框架结束:

18 68 05 DE 02 18 D0                              .h.Þ..Ð
2A 18 43 0B 0D 00 00 00 D1 1E 98 43               *.C.....Ñ.˜C
Run Code Online (Sandbox Code Playgroud)

我完全迷失在第一个.第二个与ZRINIT和ZDATA帧一样有意义.

lar*_*sks 6

我的伙伴想知道你是否正在实施一台时间机器.

我不知道我可以回答你所有的问题 - 我从来没有真正实现过zmodem - 但这里的答案很少:

从文章中提到的内容来看,有效负载是通过[ZDLE]进行转义的.那么如何传输恰好匹配[ZDLE]值的有效载荷字节?还有这样的其他价值吗?

您在问题开头链接到的文档中明确说明了这一点,其中说明:

The ZDLE character is special.  ZDLE represents a control sequence
of some sort.  If a ZDLE character appears in binary data, it is
prefixed with ZDLE, then sent   as ZDLEE.
Run Code Online (Sandbox Code Playgroud)

它经常引用ZDLE编码,但它是什么?我什么时候使用它,什么时候不使用它?

在旧时代,某些"控制字符"用于控制通信渠道(因此名称).例如,发送XON/XOFF字符可能会暂停传输.ZDLE用于转义可能存在问题的字符.根据规范,这些是默认转义的字符:

ZMODEM software escapes ZDLE, 020, 0220, 021, 0221, 023, and 0223.
If preceded by 0100 or 0300 (@), 015 and 0215 are also escaped to
protect the Telenet command escape CR-@-CR.  The receiver ignores
021, 0221, 023, and 0223 characters in the data stream.
Run Code Online (Sandbox Code Playgroud)

我环顾四周寻找参考代码,但我能找到的是从90年代早期开始的无法读取的无证件C文件.

这是否包含lrzsz包的代码?这在大多数Linux发行版中仍然可以广泛使用(并且通过已建立的ssh连接传输文件非常方便).

还有一些其他的实现在那里,其中包括对上市软件几个freecode,包括qodem, syncterm,MBSE,等等.我相信syncterm实现是作为库编写的,从你自己的代码中可以很容易地使用(但我不确定).

如果您浏览旧的MS-DOS软件集合,可能会发现其他代码.


inf*_*ing 6

我不能责怪你。用户手册的组织方式不便于用户使用

填充字节 (0x2A) 是任意的吗?

不,从第 14,15 页开始:

二进制标头以序列 ZPAD、ZDLE、ZBIN 开始。

十六进制标头以序列 ZPAD、ZPAD、ZDLE、ZHEX 开头。

规范最后没有提到 [CR] [LF] [XON],但 MSDN 文章提到了。为什么它在那里?

第15页

* * ZDLE B 类型 F3/P0 F2/P1 F1/P2 F0/P3 CRC-1 CRC-2 CR LF XON 。为什么[LF]设置了位0x80?

没有把握。从 Tera 术语开始,我将两个控制字符与 0x80 (8D 8A 11) 进行异或运算

我们有了第一个神秘的 ZCRCW 帧:[18 6B]。这个帧有多长?CRC 数据在哪里,是 CRC16 还是 CRC32?它没有在规范中的任何地方定义。

ZCRCW 不是标头或帧类型,它更像是页脚,告诉接收器接下来会发生什么。在本例中,它是包含文件名的数据子包的页脚。这将是一个 32 位校验和,因为您使用的是“C”类型的二进制标头。

  • ZDLE C型 F3/P0 F2/P1 F1/P2 F0/P3 CRC-1 CRC-2 CRC-3 CRC-4

然后我们有一个未定义类型的框架:[18 50 D3 0F F1 11]。这是一个单独的帧还是 ZCRCW 的一部分?

这就是 ZCRCW 数据子包的 CRC。它是 5 个字节,因为第一个字节是 0x10,一个需要 ZDLE 转义的控制字符。我不确定 0x11 是什么。

并且没有[XON]。

XON 仅适用于十六进制标头。您不将其用于二进制标头。

  • ZDLE A 类型 F3/P0 F2/P1 F1/P2 F0/P3 CRC-1 CRC-2 。那么如何传输恰好与 [ZDLE] 的值匹配的有效负载字节呢?

18 58(又名 ZDLEE)

18 68 05 DE 02 18 D0

这是数据子帧的页脚。接下来的 5 个字节是 CRC(最后一个字节是 ZDLE 编码)