首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >ZModem在C#中的实现- ZPOS导致的较大文件问题

ZModem在C#中的实现- ZPOS导致的较大文件问题
EN

Stack Overflow用户
提问于 2018-11-28 20:32:02
回答 1查看 461关注 0票数 0

当我尝试发送超过16kb的文件时,我的ZModem实现出现了问题。

我跟踪了与WireShark的通信,并将我的数据与TeraTerm发送的数据进行了比较。

例如,TeraTerm能够发送每种大小的文件。我面临的问题是,在某个时刻,接收设备向我发回了一个ZPOS请求。

当我尝试从给定的偏移量重新发送数据时,我的数据流被损坏。每个进一步的数据包都会导致该ZPOS响应。

这是我追踪到的与WireShark的完整通信。

使用rz\r命令调用接收器。

代码语言:javascript
复制
0000   1b 00 30 b5 45 fb 01 a2 ff ff 00 00 00 00 09 00   ..0µEû.¢ÿÿ......
0010   00 03 00 14 00 01 03 03 00 00 00 72 7a 0d         ...........rz.

启动会话

代码语言:javascript
复制
0000   1b 00 70 b1 f0 15 02 a2 ff ff 00 00 00 00 09 00   ..p±ð..¢ÿÿ......
0010   00 03 00 14 00 01 03 14 00 00 00 2a 2a 18 42 30   ...........**.B0
0020   30 30 30 30 30 30 30 30 30 30 30 30 30 0d 0a      0000000000000..

来自设备的响应

代码语言:javascript
复制
0000   1b 00 90 01 5b fb 01 a2 ff ff 00 00 00 00 09 00   ....[û.¢ÿÿ......
0010   01 03 00 14 00 81 03 15 00 00 00 2a 2a 18 42 30   ...........**.B0
0020   31 30 30 30 30 30 30 32 33 62 65 35 30 0d 8a 11   100000023be50...

然后我发送带有文件名和文件信息的文件头。

代码语言:javascript
复制
0000   1b 00 b0 fa b3 00 02 a2 ff ff 00 00 00 00 09 00   ..°ú³..¢ÿÿ......
0010   00 03 00 14 00 01 03 0a 00 00 00 2a 18 41 04 00   ...........*.A..
0020   00 01 01 aa 16                                    ...ª.

0000   1b 00 b0 f1 a1 08 02 a2 ff ff 00 00 00 00 09 00   ..°ñ¡..¢ÿÿ......
0010   00 03 00 14 00 01 03 20 00 00 00 73 61 6d 70 6c   ....... ...sampl
0020   65 2e 74 78 74 00 32 31 35 30 31 20 31 33 33 37   e.txt.21501 1337
0030   37 35 30 31 33 33 32 18 6b 83 e5                  7501332.k.å

设备的响应告诉我它已经准备好接收文件了。

代码语言:javascript
复制
0000   1b 00 90 01 5b fb 01 a2 ff ff 00 00 00 00 09 00   ....[û.¢ÿÿ......
0010   01 03 00 14 00 81 03 15 00 00 00 2a 2a 18 42 30   ...........**.B0
0020   39 30 30 30 30 30 30 30 30 61 38 37 63 0d 8a 11   900000000a87c...

之后,我发送ZData报头和所有子数据包。

代码语言:javascript
复制
0000   1b 00 b0 f1 a1 08 02 a2 ff ff 00 00 00 00 09 00   ..°ñ¡..¢ÿÿ......
0010   00 03 00 14 00 01 03 0b 00 00 00 2a 18 41 18 4a   ...........*.A.J
0020   00 00 00 00 46 ae                                 ....F®

当我尝试上传一个更大的文件时,我在上传过程中得到了一个ZRPOS响应。关于ZModem规范,接收器告诉我在给定的偏移量处恢复。

代码语言:javascript
复制
0000   1b 00 90 01 5b fb 01 a2 ff ff 00 00 00 00 09 00   ....[û.¢ÿÿ......
0010   01 03 00 14 00 81 03 15 00 00 00 2a 2a 18 42 30   ...........**.B0
0020   39 30 30 34 30 30 30 30 30 62 35 64 31 0d 8a 11   900400000b5d1...

但是每个另外的子包从接收设备得到相同的响应。

下面是我完成的负责发送文件的实现。

代码语言:javascript
复制
private void SendZDATAPackets(byte[] src, CRC16CCIT crcCalculator)
{
    // Chunk size
    var chunkSize = 1024;

    // Create ZDATA header
    var zdataHeaderQueue = new Queue<byte>();
    var zdataHeaderCommand = Utils.BuildDataCommand(HeaderType.ZDATA, 0, 0, 0, 0);

    foreach (var c in zdataHeaderCommand)
    {
        zdataHeaderQueue.Enqueue((byte)c);
    }

    // Send ZDATA header
    SendCommand(zdataHeaderQueue.ToArray());

    ResponseHeader zdataResponse = null;

    // Slice binary data into chunks.
    for (int i = 0; i < src.Length; i += chunkSize)
    {
        // Slice data
        var dataSlice = src
            .Skip(i)
            .Take(chunkSize)
            .ToArray();

        // Send ZCRCG, if its the last part of the data send ZCRCE
        var requiredSequence = (i + dataSlice.Length) < src.Length ? ZDLESequence.ZCRCG : ZDLESequence.ZCRCE;

        if (zdataResponse?.ZHeader == HeaderType.ZRPOS)
        {
            /*
             * A ZRPOS header resets the sender's file offset to the correct position.
             * If possible, the sender should purge its output buffers and/or networks
             * of all unprocessed output data, to minimize the amount of unwanted data
             * the receiver must discard before receiving data starting at the correct
             * file offset. The next transmitted data frame should be a ZCRCW frame
             * followed by a wait to guarantee complete flushing of the network's memory.
             */
            SerialPort.DiscardOutBuffer();

            dataSlice = src
                .Skip(zdataResponse.RequestedOffset)
                .Take(chunkSize)
                .ToArray();

            requiredSequence = ZDLESequence.ZCRCW;
        }

        // Create data queue for the sliced data.
        var queue = new Queue<byte>(dataSlice);

        // Calculate CRC
        var dataForCrcCalculation = dataSlice.Concat(new byte[] { (byte)requiredSequence }).ToArray();
        var crc = crcCalculator.ComputeChecksumAsBytes(dataForCrcCalculation);

        // Add crc
        queue.Enqueue((byte)ControlBytes.ZDLE);
        queue.Enqueue((byte)requiredSequence);
        queue.Enqueue(crc[0]);
        queue.Enqueue(crc[1]);

        // Send data
        var zdataCommand = queue.ToArray();
        zdataResponse = SendCommand(zdataCommand);
    }
}

有没有人在实现过程中遇到了同样的问题,可以给我指个方向来解决这个问题?

谢谢!

EN

回答 1

Stack Overflow用户

发布于 2018-12-08 17:12:20

如果有人需要在C#中使用原生ZModem实现,我现在就设法让它工作起来。

问题是我发送的字节没有ZDLE编码。ZModem要求对数据包以及附加在末尾的CRC进行编码,以转义某些字符。然而,如果你使用CRC16,你就不需要编码了。

我创建了一个GitHub存储库,这样任何人都可以使用它。然而,该功能仅限于将数据上载到远程设备。不过,实现下载应该没有问题。

https://github.com/datoml/zmodem-dotnet-standard

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/53519554

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档