这些天要写一个通信协议封解包程序,要用到CRC16校验,协议中关于CRC的资料如下图:
![crc.JPG](http://studygolang.qiniudn.com/170210/294de19673a9adfae8391297bd2bf447.JPG)
我参考了一下别人用Java写的CRC16函数
public static String getCrc(byte[] data) {
int high;
int flag;
int wcrc = 0xffff;
for (int i = 0; i < data.length; i++) {
high = wcrc >> 8;
wcrc = high ^ data[i];
for (int j = 0; j < 8; j++) {
flag = wcrc & 0x0001;
wcrc = wcrc >> 1;
if (flag == 1)
wcrc ^= 0xa001;
}
}
return Integer.toHexString(wcrc);
}
由于找不到golang现成的crc6相关的函数,它只有crc32的,然后用golang实现了一个:
func Crc16Verify(msg string) {
//16位全为1的寄存器
var crc uint16 = 0xFFFF
//高8位字节
var HighByte uint16
//移出的数位
var flag uint16
var msgBytes []byte = []byte(msg) //被校验的信息
var length int = len(msgBytes) //被校验的信息的长度
for i := 0; i < length; i++ {
HighByte = crc >> 8 // 16位寄存器的高位字节
crc = HighByte ^ uint16(msgBytes[i]) //取被校验串的一个字节与16位寄存器的高位字节进行异或运算
for j := 0; j < 8; j++ {
flag = crc & 0x0001 //移出的数位
crc = crc >> 1 // 把这个 16 寄存器向右移一位
if flag == 0x0001 { //移出位是1与多项式0xA001异或
crc ^= 0xA001
}
}
}
//crc = (crc << 8) ^ (crc >> 8)//高低字节对调
fmt.Printf("%#x\n", crc)
}
在Crc16Verify("1234")的时候,输出0x9181,同时Java版本的输出9181,但是用crc16校验工具算出的是1012和c613,没有一个对得上的。
![crc1.JPG](http://studygolang.qiniudn.com/170210/c8b8a56ef36e68ad851fa7c1e0e0f524.JPG)
![2.JPG](http://studygolang.qiniudn.com/170210/2ce2931e8d83774479e4074d96487bbf.JPG)
小弟实在不知道错在哪里了,这个问题困扰了一天多,麻烦各位go大神指教指教!
算法不了解,但从代码上看,输入值的处理存在问题哦。
原始数值(16进制):1234,可不是字符串“1234”直接[]byte。
至少也应该用binary包来写入。比如:
```go
b := make([]byte, 2)
binary.BigEndian.PutUint16(b, 0x1234)
fmt.Printf("%x\n", b)
Crc16Verify(b)//该方法只需要对[]byte直接位运算
```
希望有所帮助!
#1
更多评论
github有一个比较好的代码,可以去看看:
https://github.com/howeyc/crc16/blob/master/crc16.go
#2