2

C++ xmodem プロトコルを C# に移植していますが、CRC チェックに問題があります。アプリケーションは、CRC 付きの xmodem 128 バイト プロトコルを使用して、モデム経由でファイルをアップロードします。ハイパーターミナルを使用してテストします。小さなファイルは問題なくアップロードできますが、大きなファイル (50K 以上) を試すと、下位バイトと上位バイトが 255 のときに常に CRC が壊れます。ありがとう!

これがCRCコードです...

..
    if (check(true, _data, 3, 133))
                                {
                                    _currentState = State.Good;
                                }
                                else
                                {
                                    _currentState = State.Bad;


}
...
private bool check(bool isCRC, byte[] buf, int index, int sz)
        {
            if (isCRC) // use CRC checking
            {
                ushort crc = CRC16.CRC16_ccitt(buf, index, sz);
                ushort tcrc = (ushort)((buf[sz + index] << 8) + buf[sz + index + 1]);
                if (crc == tcrc)
                {

                    return true;
                }
            }
            else
            { // use Checksum checking
                int i;
                byte cks = 0;
                for (i = 0; i < sz; ++i)
                {
                    cks += buf[i + index];
                }
                if (cks == buf[sz + index])
                    return true;
            }
            return false;
        }

internal static class CRC16
{
    #region Members

    //size = 256
    private static ushort[] crc16tab = {
      0x0000,0x1021,0x2042,0x3063,0x4084,0x50a5,0x60c6,0x70e7,
      0x8108,0x9129,0xa14a,0xb16b,0xc18c,0xd1ad,0xe1ce,0xf1ef,
      0x1231,0x0210,0x3273,0x2252,0x52b5,0x4294,0x72f7,0x62d6,
      0x9339,0x8318,0xb37b,0xa35a,0xd3bd,0xc39c,0xf3ff,0xe3de,
      0x2462,0x3443,0x0420,0x1401,0x64e6,0x74c7,0x44a4,0x5485,
      0xa56a,0xb54b,0x8528,0x9509,0xe5ee,0xf5cf,0xc5ac,0xd58d,
      0x3653,0x2672,0x1611,0x0630,0x76d7,0x66f6,0x5695,0x46b4,
      0xb75b,0xa77a,0x9719,0x8738,0xf7df,0xe7fe,0xd79d,0xc7bc,
      0x48c4,0x58e5,0x6886,0x78a7,0x0840,0x1861,0x2802,0x3823,
      0xc9cc,0xd9ed,0xe98e,0xf9af,0x8948,0x9969,0xa90a,0xb92b,
      0x5af5,0x4ad4,0x7ab7,0x6a96,0x1a71,0x0a50,0x3a33,0x2a12,
      0xdbfd,0xcbdc,0xfbbf,0xeb9e,0x9b79,0x8b58,0xbb3b,0xab1a,
      0x6ca6,0x7c87,0x4ce4,0x5cc5,0x2c22,0x3c03,0x0c60,0x1c41,
      0xedae,0xfd8f,0xcdec,0xddcd,0xad2a,0xbd0b,0x8d68,0x9d49,
      0x7e97,0x6eb6,0x5ed5,0x4ef4,0x3e13,0x2e32,0x1e51,0x0e70,
      0xff9f,0xefbe,0xdfdd,0xcffc,0xbf1b,0xaf3a,0x9f59,0x8f78,
      0x9188,0x81a9,0xb1ca,0xa1eb,0xd10c,0xc12d,0xf14e,0xe16f,
      0x1080,0x00a1,0x30c2,0x20e3,0x5004,0x4025,0x7046,0x6067,
      0x83b9,0x9398,0xa3fb,0xb3da,0xc33d,0xd31c,0xe37f,0xf35e,
      0x02b1,0x1290,0x22f3,0x32d2,0x4235,0x5214,0x6277,0x7256,
      0xb5ea,0xa5cb,0x95a8,0x8589,0xf56e,0xe54f,0xd52c,0xc50d,
      0x34e2,0x24c3,0x14a0,0x0481,0x7466,0x6447,0x5424,0x4405,
      0xa7db,0xb7fa,0x8799,0x97b8,0xe75f,0xf77e,0xc71d,0xd73c,
      0x26d3,0x36f2,0x0691,0x16b0,0x6657,0x7676,0x4615,0x5634,
      0xd94c,0xc96d,0xf90e,0xe92f,0x99c8,0x89e9,0xb98a,0xa9ab,
      0x5844,0x4865,0x7806,0x6827,0x18c0,0x08e1,0x3882,0x28a3,
      0xcb7d,0xdb5c,0xeb3f,0xfb1e,0x8bf9,0x9bd8,0xabbb,0xbb9a,
      0x4a75,0x5a54,0x6a37,0x7a16,0x0af1,0x1ad0,0x2ab3,0x3a92,
      0xfd2e,0xed0f,0xdd6c,0xcd4d,0xbdaa,0xad8b,0x9de8,0x8dc9,
      0x7c26,0x6c07,0x5c64,0x4c45,0x3ca2,0x2c83,0x1ce0,0x0cc1,
      0xef1f,0xff3e,0xcf5d,0xdf7c,0xaf9b,0xbfba,0x8fd9,0x9ff8,
      0x6e17,0x7e36,0x4e55,0x5e74,0x2e93,0x3eb2,0x0ed1,0x1ef0
  };

    #endregion Members

    #region Implementation

    static public ushort CRC16_ccitt(byte[] buf, int index, int len)
    {
        int counter;
        ushort crc = 0;
        for (counter = 0; counter < len; counter++)
            crc = (ushort)((crc << 8) ^ crc16tab[((crc >> 8) ^ buf[index + counter]) & 0x00FF]);
        return crc;
    }

    #endregion Implementation
}

これが失敗する 133 バイトの配列です。

    [0] 1   byte
    [1] 127 byte
    [2] 128 byte
    [3] 84  byte
    [4] 52  byte
    [5] 51  byte
    [6] 49  byte
    [7] 48  byte
    [8] 50  byte
    [9] 51  byte
    [10]    57  byte
    [11]    50  byte
    [12]    48  byte
    [13]    70  byte
    [14]    48  byte
    [15]    48  byte
    [16]    48  byte
    [17]    48  byte
    [18]    48  byte
    [19]    48  byte
    [20]    48  byte
    [21]    48  byte
    [22]    48  byte
    [23]    48  byte
    [24]    84  byte
    [25]    32  byte
    [26]    32  byte
    [27]    32  byte
    [28]    32  byte
    [29]    32  byte
    [30]    32  byte
    [31]    32  byte
    [32]    32  byte
    [33]    32  byte
    [34]    32  byte
    [35]    32  byte
    [36]    32  byte
    [37]    32  byte
    [38]    32  byte
    [39]    32  byte
    [40]    32  byte
    [41]    32  byte
    [42]    32  byte
    [43]    32  byte
    [44]    32  byte
    [45]    32  byte
    [46]    32  byte
    [47]    32  byte
    [48]    32  byte
    [49]    32  byte
    [50]    32  byte
    [51]    32  byte
    [52]    32  byte
    [53]    32  byte
    [54]    32  byte
    [55]    32  byte
    [56]    32  byte
    [57]    32  byte
    [58]    32  byte
    [59]    32  byte
    [60]    32  byte
    [61]    32  byte
    [62]    32  byte
    [63]    32  byte
    [64]    32  byte
    [65]    32  byte
    [66]    32  byte
    [67]    32  byte
    [68]    32  byte
    [69]    48  byte
    [70]    49  byte
    [71]    45  byte
    [72]    32  byte
    [73]    32  byte
    [74]    32  byte
    [75]    32  byte
    [76]    32  byte
    [77]    32  byte
    [78]    32  byte
    [79]    32  byte
    [80]    32  byte
    [81]    32  byte
    [82]    13  byte
    [83]    10  byte
    [84]    80  byte
    [85]    48  byte
    [86]    51  byte
    [87]    66  byte
    [88]    90  byte
    [89]    66  byte
    [90]    32  byte
    [91]    53  byte
    [92]    55  byte
    [93]    54  byte
    [94]    53  byte
    [95]    53  byte
    [96]    48  byte
    [97]    48  byte
    [98]    48  byte
    [99]    48  byte
    [100]   84  byte
    [101]   52  byte
    [102]   51  byte
    [103]   77  byte
    [104]   79  byte
    [105]   51  byte
    [106]   55  byte
    [107]   49  byte
    [108]   56  byte
    [109]   48  byte
    [110]   48  byte
    [111]   48  byte
    [112]   48  byte
    [113]   48  byte
    [114]   48  byte
    [115]   48  byte
    [116]   48  byte
    [117]   48  byte
    [118]   48  byte
    [119]   56  byte
    [120]   57  byte
    [121]   52  byte
    [122]   48  byte
    [123]   52  byte
    [124]   57  byte
    [125]   32  byte
    [126]   32  byte
    [127]   32  byte
    [128]   32  byte
    [129]   32  byte
    [130]   32  byte
    [131]   255 byte
    [132]   255 byte

更新 シリアルポートから読み取っていないことに言及しませんでした。コールを受信し、TCP/IP を使用してサービスへの接続を開くモデム バンクがあります。したがって、バイトを読み取るときは、TcpClients ストリームから読み取っています。

また、ハイパーターミナルを使用して自分のサービスにファイルを送信すると、パケット 255 のパケット番号は 255 で、補数は 255 であることに気付きました。補数は 0 のはずですよね?

4

2 に答える 2

1

私は自分が抱えていた問題を理解しました。まず、私のセットアップ。着呼を受け取り、telnet TCP/IP を使用してそれらを Windows ボックスで実行されているサービスにルーティングするモデム バンクがあります。私が抱えていた問題は、クライアントが 255 バイトを送信するたびに、その前に 255 バイトがあったことでした。255 は xmodem パケット番号の有効なバイトであるため、2 つのパケットを送信したときに問題が発生したため、パケット番号が補完され、CRC が行われます。255 バイトを 2 つ送信した理由は、Telnet TCP/IP がバイト 255 を使用するためです。したがって、255 バイトを送信する必要がある場合、Telnet は別の 255 バイトでそれをエスケープします。シリアル接続で作業していた場合、これは決して起こらなかったでしょう。モデム バンクは telnet TCP/IP を使用してサービスに接続するため、エスケープされる 255 バイトを処理する必要があります。それをしたら、すべてがうまくいきました。Hans Passant と Tergiver' を使用しました。

于 2011-03-16T13:35:36.863 に答える
1

それが問題だとは思わないため、CRCに関する他の「回答」を削除しました。Dan はコメントで、http://trackday.cc/b2evo/blog2.php/2007/08/02/net-xmodemからコードを入手したと述べました。元の質問に貼り付けられたコードは、そのソースから直接取得されます。

私はそれをダウンロードして、それを見始めました。多くの欠陥 (*) があり、ほとんどが致命的ではありません。ただし、この部分は XModemReceive メソッドで私に飛びつきました:

#region fill packet with datastream

xbuff[0] = (byte)c;
for (i = 0; i < (bufsz + (useCRC ? 1 : 0) + 3); i++)
{
    xbuff[i + 1] = (byte)this.port.ReadByte();
}

#endregion

SerialPort.ReadByte が End Of Stream に遭遇した場合、-1 (つまり、バイト形式で 255) を返します。ReadByte がタイムアウトした場合、TimeoutException が発生します。EOS が発生した場合、正しいアクションは、現在のパケットを中止することです。私はそれを考えるのに時間を費やしていません。

最初に、これが実際に発生している問題であるかどうかをテストするためだけに、そのコードを変更します。

xbuff[0] = (byte)c;
for (i = 0; i < (bufsz + (useCRC ? 1 : 0) + 3); i++)
{
    int byteValue = this.port.ReadByte();
    Debug.Assert(byteValue >= 0, "byteValue >= 0");
    xbuff[i + 1] = (byte)byteValue;
}

これは修正ではなく、単なるテストです。(デバッグ ビルドで) アサートしている場合は、それを修正することを考えることができます。

(*)最初のいくつかの「欠陥」についてブログに書きました。

于 2011-03-13T16:11:46.470 に答える