我需要在我的程序中包含基本的文件发送和文件接收例程,它需要通过ZMODEM协议。问题是我无法理解规范。
供参考,here is the specification。
规范没有定义各种常量,所以这里是a header file from Google。
在我看来,在该文件中还有很多重要的事情未定义:
我环顾四周寻找参考代码,但是我能找到的是从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.Š.
有三个问题:
此后,客户端需要发送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标志问题,我还有两个问题:
服务器以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Ó.ñ.
这甚至没有标题,它只是直接跳转到数据。好的,我可以忍受。但是:
客户端需要使用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帧一样有意义。
答案 0 :(得分: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.
它经常引用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.
我四处寻找参考代码,但我能找到的只是 来自90年代初的不可读的,未记录的C文件。
这是否包含lrzsz包的代码?这仍然是 在大多数Linux发行版中广泛使用(并且非常方便 通过已建立的ssh连接传输文件。)
还有许多其他实现,包括 freecode中列出的几个软件,包括qodem, syncterm,MBSE和其他人。我相信syncterm implementation是作为库编写的,可能很合理 从你自己的代码中使用(但我不确定)。
如果你在旧的集合中搜索,你可能会发现其他代码 MS-DOS软件。
答案 1 :(得分:1)
我不能责怪你。用户手册不是以用户友好的方式组织的
填充字节(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仅适用于Hex标头。你不能将它用作二进制标题。
- ZDLE A型F3 / P0 F2 / P1 F1 / P2 F0 / P3 CRC-1 CRC-2 。 那么如何传输恰好与[ZDLE]的值匹配的有效载荷字节?
18 58(AKA ZDLEE)
18 68 05 DE 02 18 D0
这是数据子帧的页脚。接下来的5个字节是CRC(最后一个字节是ZDLE编码的)