Протокол Xmodem-CRC в проблеме c # - PullRequest
2 голосов
/ 12 марта 2011

Я портирую протокол C ++ xmodem на C #, и у меня возникла проблема с проверкой CRC. Приложение загружает файлы через модем, используя 128-битный протокол xmodem с CRC. Я проверяю это с помощью Гипертерминала. Я могу нормально загружать небольшие файлы, но когда я пробую большие файлы (50K +), CRC всегда прерывается, когда младший и старший байты равны 255. Может ли кто-нибудь помочь мне с этим? Спасибо!

Вот код 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

UPDATE Я не упомянул, что я не читаю с последовательного порта. У нас есть модемный банк, который принимает звонки и открывает соединение с нашим сервисом, используя TCP / IP. Поэтому, когда я читаю байты, я читаю из потока TcpClients.

Я также заметил, что когда я отправляю файл в мою службу с использованием Hyperterminal, пакет 255 имеет номер пакета 255 и комплимент 255. Комплимент должен быть 0, верно?

Ответы [ 2 ]

1 голос
/ 16 марта 2011

Я выяснил проблему, с которой столкнулся. Во-первых, мои настройки. У нас есть модемный банк, который принимает входящие звонки и маршрутизирует их, используя telnet TCP / IP, на службу, работающую в окне Windows. У меня была проблема, каждый раз, когда клиент отправлял 255 байт, ему предшествовал 255 байт. Поскольку 255 является действительным байтом для номеров пакетов xmodem, комплимент номера пакета и CRC это потому, что проблема, когда он отправил два из них. Причина, по которой он отправлял два 255 байтов, заключалась в том, что Telnet TCP / IP использует байт 255. Таким образом, когда необходимо отправить 255 байт, Telnet избегает его с другими 255 байтами. Этого бы никогда не случилось, если бы я работал через последовательное соединение. Так как наш модемный банк подключается к нашему сервису с помощью telnet TCP / IP, нам нужно обработать 255 байтов, которые экранированы. Как только я это сделал, все работало отлично. Я воспользовался советом Ханса Пассанта и Тергивера, чтобы исправить ошибки в моем коде xmodem, поэтому большое спасибо им за помощь.

1 голос
/ 13 марта 2011

Удален мой другой «ответ» о КПР, потому что я не думаю, что это проблема.Дэн упомянул в комментарии, что он получил код от 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;
}

Это неисправить, просто тест.Если он утверждает (в сборке отладки), тогда мы можем подумать об его исправлении.

(*) Я написал о первых нескольких «недостатках», если вы заинтересованы в чтениио них.

...