【发布时间】:2015-04-01 03:19:36
【问题描述】:
我需要在我的程序中包含基本的文件发送和文件接收例程,并且它需要通过 ZMODEM 协议。问题是我无法理解规范。
供参考,here is the specification。
规范没有定义各种常量,所以这里是a header file from 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(您可能需要通过Google's cache 查看)
为了说明我的困难,这里是一个简单的例子。我在服务器上创建了一个包含“Hello world!”的纯文本文件,它被称为 helloworld.txt。
我使用以下命令从服务器发起传输:
sx --zmodem helloworld.txt
这会提示服务器发送以下 ZRQINIT 帧:
2A 2A 18 42 30 30 30 30 30 30 30 30 30 30 30 30 **.B000000000000
30 30 0D 8A 11 00.Š.
这三个问题:
- 填充字节(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.Š
除了 [LF] 0x80 标志问题,我还有两个问题:
- 为什么这次不包括 [XON]?
-
CRC 是根据二进制数据还是 ASCII 十六进制数据计算的?如果是二进制数据,我得到 0x197C,如果是 ASCII 十六进制数据,我得到 0xF775;这些都不是帧中的实际内容(0xBE50)。(已解决;它遵循您使用的任何模式。如果您处于 BIN 或 BIN32 模式,则它是二进制数据的 CRC。如果您在 ASCII 十六进制模式下,它是由 ASCII 十六进制字符表示的内容的 CRC。)
服务器以 ZFILE 帧响应:
2A 18 43 04 00 00 00 00 DD 51 A2 33 *.C.....ÝQ¢3
好的。这是有道理的。如果我计算 [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Ó.ñ.
这甚至没有标题,它只是直接跳转到数据。好吧,我可以忍受。然而:
- 我们有了第一个神秘的 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.Š
与 ZRINIT 帧的问题相同:CRC 错误,[LF] 设置了位 0x80,并且没有 [XON]。
服务器以 ZDATA 帧响应:
2A 18 43 0A 00 00 00 00 BC EF 92 8C *.C.....¼ï’Œ
与 ZFILE 相同的问题:CRC 一切正常,但 [CR] [LF] [XON] 在哪里?
在此之后,服务器发送文件的有效负载。由于这是一个简短的示例,它适合一个块(最大大小为 1024):
48 65 6C 6C 6F 20 77 6F 72 6C 64 21 0A Hello world!.
从文章似乎提到的内容来看,有效载荷是用 [ZDLE] 转义的。那么如何传输恰好与 [ZDLE] 的值匹配的有效负载字节呢?还有其他类似的值吗?
服务器以这些帧结束:
18 68 05 DE 02 18 D0 .h.Þ..Ð
2A 18 43 0B 0D 00 00 00 D1 1E 98 43 *.C.....Ñ.˜C
我对第一个完全迷失了。第二个与 ZRINIT 和 ZDATA 帧一样有意义。
【问题讨论】:
-
出于同样的原因,我正在做同样的事情;如果你曾经做过这项工作,并且有源代码,那就太棒了......
-
结果如何?在花了几天的时间编写代码以获得可靠的 zmodem 接收工作后,我放弃了,只是向 lrz 发起了攻击。一天工作。它远没有那么干净,但我真的不想花更多时间在一个古老但过时的协议上......
-
另外,当心!我在那里发现了一些其他的 zmodem 代码库,但它们都完全不可靠!我尝试的文件中可能有 5% 以失败告终,而且我什至没有尝试利用极端情况。确保您使用经过实战考验的代码,而不是某人的周末项目。