前言
在网络传输过程中会存在粘包、半包等问题,在各个厂家做物联网产品的时候,大多会定义一种协议,协议里面包含了数据的包头、包尾以及校验位等字节,主要目的是为了在我们做物联网服务网关(接收物联网设备传输数据的系统)的时候方便对接收的数据进行校验以及处理粘包与半包问题。
为了防止消息体里面出现与包头包尾相同的字节出现,在物联网设备进行组包的时候一般会进行转移,就是将消息体中出现与包头包尾相同的字节按特定的规则转成其他字节。
比如:JT/T808协议,会将除包头包尾外整个消息体中出现的
0x7E——>0x7D 0x02
0x7D——>0x7D 0x01
所以我们在网关程序接收到设备的原始数据的时候,去掉包头、包尾之后需要进行反转义,然后将反转义后的数据在进行解析分析。
反转义:
0x7D 0x01——>0x7D
0x7D 0x02——>0x7E
C#实现
C#转义实现
/// <summary>
/// 息头、消息体、校验码中0x7E转义为0x7D 0x02,0x7D转义为0x7D 0x01
/// </summary>
/// <param name="inbytes"></param>
/// <returns></returns>
public byte[] escape(byte[] inbytes)
{
List<byte> list = new List<byte>();
for (int i = 0; i < inbytes.Length; i++)
{
byte b = inbytes[i];
if (b == 0x7e)
{
list.Add(0x7d);
list.Add(0x02);
}
else if (b == 0x7d)
{
list.Add(0x7d);
list.Add(0x01);
}
else
{
list.Add(b);
}
}
return list.ToArray();
}
C#反转义实现
/// <summary>
/// 消息头、消息体、校验码中0x7D 0x02反转义为0x7E,0x7D 0x01反转义为0x7D
/// </summary>
/// <param name="inbytes"></param>
/// <returns></returns>
public byte[] unescape(byte[] inbytes)
{
List<byte> list = new List<byte>();
int i = 0;
int bodyLength = inbytes.Length;
if (i < bodyLength)
{
byte firstByte = inbytes[i];
if (firstByte == 0x7d)
{
byte nextByte = inbytes[i + 1];
if (nextByte == 0x01)
{
list.Add(0x7d);
}
else if (nextByte == 0x02)
{
list.Add(0x7e);
}
else
{
list.Add(firstByte);
list.Add(nextByte);
}
i += 2;
}
else
{
list.Add(firstByte);
i++;
}
}
return list.ToArray();
}
Java实现
基于Netty框架
JAVA 转义实现
/**
* 消息头、消息体、校验码中0x7E转义为0x7D 0x02,0x7D转义为0x7D 0x01
*
* @param out
* @param bodyBuf
*/
public static void escape(ByteBuf out, ByteBuf bodyBuf) {
while (bodyBuf.readableBytes() > 0) {
int b = bodyBuf.readUnsignedByte();
if (b == 0x7E) {
out.writeShort(0x7D02);
} else if (b == 0x7D) {
out.writeShort(0x7D01);
} else {
out.writeByte(b);
}
}
}
JAVA 反转义实现
/**
* 消息头、消息体、校验码中0x7D 0x02反转义为0x7E,0x7D 0x01反转义为0x7D
*
* @param in
* @param frame
* @param bodyLen
*/
public static void unescape(ByteBuf in, ByteBuf frame, int bodyLen) {
int i = 0;
while (i < bodyLen) {
int b = in.readUnsignedByte();
if (b == 0x7D) {
int nextByte = in.readUnsignedByte();
if (nextByte == 0x01) {
frame.writeByte(0x7D);
} else if (nextByte == 0x02) {
frame.writeByte(0x7E);
} else {
//异常数据
frame.writeByte(b);
frame.writeByte(nextByte);
}
i += 2;
} else {
frame.writeByte(b);
i++;
}
}
}