计算PPP帧检查序列

问题描述:

我正在尝试使用C#生成一个有效的PPP帧检查序列(FCS)。我已经实施的代码基于this answer计算PPP帧检查序列

public static class Crc16 
{ 
    const ushort polynomial = 0x8408; 
    static readonly ushort[] fcstab = new ushort[256]; 

    // This is the fcstab from RFC1662 
    // https://tools.ietf.org/html/rfc1662#ref-7 
    //static readonly ushort[] fcstab = new ushort[] { 
    //  0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf, 
    //  0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7, 
    //  0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e, 
    //  0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876, 
    //  0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd, 
    //  0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5, 
    //  0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c, 
    //  0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974, 
    //  0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb, 
    //  0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3, 
    //  0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a, 
    //  0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72, 
    //  0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9, 
    //  0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1, 
    //  0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738, 
    //  0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70, 
    //  0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7, 
    //  0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff, 
    //  0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036, 
    //  0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e, 
    //  0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5, 
    //  0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd, 
    //  0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134, 
    //  0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c, 
    //  0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3, 
    //  0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb, 
    //  0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232, 
    //  0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a, 
    //  0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1, 
    //  0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9, 
    //  0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330, 
    //  0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78 
    // }; 

    static Crc16() 
    { 
     ushort value; 
     ushort temp; 
     for (ushort i = 0; i < fcstab.Length; ++i) 
     { 
      value = 0; 
      temp = i; 
      for (byte j = 0; j < 8; ++j) 
      { 
       if (((value^temp) & 0x0001) != 0) 
       { 
        value = (ushort)((value >> 1)^polynomial); 
       } 
       else 
       { 
        value >>= 1; 
       } 
       temp >>= 1; 
      } 
      fcstab[i] = value; 
     } 
    } 

    /// <summary>Method that computes the checksum.</summary> 
    /// <param name="buff">The input <see cref="byte[]"/> to calculate the checksum off of.</param> 
    /// <example> 
    /// byte[] fcs = Crc16.ComputeChecksumBytes(buff) 
    /// </example> 
    /// <returns></returns> 
    public static byte[] ComputeChecksumBytes(byte[] buff) 
    { 
     ushort fcs = 0xFFFF; 
     for (int i = 0; i < buff.Length; i++) 
     { 
      byte index = (byte)((fcs^buff[i]) & 0xff); 
      fcs = (ushort)((fcs >> 8)^fcstab[index]); 
     } 
     fcs ^= 0xFFFF; 
     var lsb = (fcs >> 8) & 0xff; 
     var msb = fcs & 0xff; 
     return new byte[] { (byte)msb, (byte)lsb }; 
    } 
} 

良好的部分是,获取生成的FCS表(fcstab[])是RFC 1662看出因此证实在构造编码是正确的相同的表。

该问题似乎与ComputeChecksumBytes()方法。

我有一个输入PPP数据包7E FF 03 C0 21 01 00 00 0E 02 06 00 00 00 00 07 02 08 02 DD 31 7E

我从this link知道,“FCS计算在整个 PPP数据包,不包括启动和停止标志(7E)。”这给我留下了FF 03 C0 21 01 00 00 0E 02 06 00 00 00 00 07 02 08 02 DD 31

我也从that link知道FCS八比特组(DD 31)要“等于零”。这使我与FF 03 C0 21 01 00 00 0E 02 06 00 00 00 00 07 02 08 02 00 00

当我用该输入字节数组调用Crc16.ComputeChecksumBytes时,我的实际计算FCS结果为C0 0E

我所做的一切似乎都是正确的,但我仍然不知道为什么我没有得到在原始数据包中计算的DD 31

任何帮助将不胜感激!

+1

零应该是'c00e',而不是'2d24'。一定还有其他的错误。 –

只要做到没有两个0的结尾。

+2

一些额外的解释对未来的读者会有好处。你是一个非常高的代表用户,你知道好的答案通常有更多的解释,否则他们会被标记(就像这样做!)。我相信它可能会回答这个问题,但你需要解释它为什么会这样做。 - 来自评论。 –

+1

OP将需要解释为什么他们把两个0放在第一位!我不知道他们为什么这样做。 –

+0

是的,我承认我很困惑,但我觉得我至少应该留下评论,这样我可以在评论队列中点击'看起来好'按钮! –