最近在做一个TCP通讯项目时,用到了SLIP(Serial Line Internet Protocol,串行线路网际协议)协议。该协议我就不介绍了网上资料一大堆。
通信数据报采用了简单的帧封装结构,此协议基于SLIP(Serial Line IP,串行线路IP协议,具体内容参见RFC1055),但加入一个校验(Checksum)字节,其值为除首尾END字符外的所有字符字节按位和。
这里面遇到了两个问题:
1,如何计算校验和,因为以前没做过查了很多资料才弄明白。就是第一位与第二位异或,得出的结果再与第三位异或!
http://baike.baidu.com/view/5705563.htm 数据校验 --bcc异或校验法(block check character)
http://msdn.microsoft.com/zh-cn/library/zkacc7k1.aspx ^ 运算符(C# 参考)
http://hi.baidu.com/zhaoxin4353270/item/c75581a9dc681512a8cfb7ac
2,发送报文定义的数组大小都是固定484,但是有时候实际大小用不到,可能只用到38个长度,后面就剩下很多空的,这个时候我需要把38个字节的数组取出来,其他的不需要。
报文封装代码:
byte END_CHAR = 0xC0; /* 分组结束标记 */
byte ESC_CHAR = 0xDB; /* 填充字节标记*/
byte ESC_END = 0xDC; /* ESC ESC_END 表示数据字节END */
byte ESC_ESC = 0xDD; /* ESC ESC_ESC 表示数据字节ESC */
/// <summary>
/// 报文封装
/// </summary>
/// <param name="inBuf">需要合并的数组</param>
/// <param name="outBuf">新的数组,用来发送报文</param>
private void SetOutBuf(byte[] inBuf, ref byte[] outBuf)
{
int index = 0; //outBuf开始处的索引
byte chVerify = 0;//校验和
int inBufSize = inBuf.Length;
// Head END_CHAR
outBuf[index++] = END_CHAR;
// Data Elements
//如果长度过长需要拆分成多个报文发送[待处理]
for (int i = 0; i < inBufSize; i++)
{
switch (inBuf[i])
{
case 0xC0: //转码处理
outBuf[index++] = ESC_CHAR;
chVerify ^= ESC_CHAR;
outBuf[index++] = ESC_END;
chVerify ^= ESC_END;
break;
case 0xDB: //转码处理
outBuf[index++] = ESC_CHAR;
chVerify ^= ESC_CHAR;
outBuf[index++] = ESC_ESC;
chVerify ^= ESC_ESC;
break;
default:
outBuf[index++] = inBuf[i];
chVerify ^= inBuf[i]; //计算效验和
break;
}
}
outBuf[index++] = chVerify;
// Tail END_CHAR
outBuf[index++] = END_CHAR;
//获取我需要的实际的报文数据
IEnumerable<byte> refBuf = outBuf.Take<byte>(index);
outBuf = refBuf.ToArray();
}