C# 优雅处理通信中的粘包和断包(二) 处理非固定长度的协议
前言
上篇文章中我们讲了一下固定长度的协议该怎么样使用解包器去解析,那今天我们再补充一点,就是非固定程度的协议该怎么样使用解包器去解析
分析协议格式
我这里设计了一个协议,它长成这个样子:
我们来一起分析一下这个协议,协议头部这里设计的是a a b b。
第二部分是长度,也就是说到这一位往后还要接收多长的数据。
然后看数据长度占一个字节,假如数据位长度标记为n时,数据部分里有多少字节的数据呢?如果我们的这个长度里面的值是n的话,那数据位的长度就是n减1,最后一位是校验校验位占一个字节。
我们看第一个实例,AABB为起始头部。然后长度位里面标记着是7,也就是说从这一位往后,我还要接收7个字节的数据。
最后一位是我们的校验位,校验位校验的是从AABB起始位之后校验位之前的这一段数据;
下一个例子也是一样的,数据内如加校验位一共是4个字节,校验和计算的是从AABB起始位之后校验位之前这段数据的Checksum.
视频教程
【女朋友都能学会】C# 协议解包器(优雅处理粘包断包)
源代码
让我们来看一下代码该怎么实现它。
在上一篇文章《解包器的基础用法》中实现的解包器它的协议是固定的八位长度,所以在计算包长度的时候就给了一个默认的八位,实现起来非常的简单。
我们今天再实现一个,按照上方这个协议去实现一个与之匹配的解包器。
/// <summary>
/// 非固定长度的协议解包器
/// 数据包长度存放于数据包内指定位
/// </summary>
public class SimpleData2Unpacker : Unpacker
{
public SimpleData2Unpacker()
{
StartMark = new byte[] { 0xAA, 0xBB };
}
protected override int CalculatePacketLength(IEnumerable<byte> bytes)
{
if (bytes.Count() < 3)
{
return 0;
}
else
{
return bytes.ElementAt(2) + 3;
}
}
}
我们需要重写这个计算包长度的方法,之前是固定的长度是个固定长度是八,我们现在是根据协议来计算它的长度的,就要重写一下这个方法。
我们至少需要知道几位才可以确定整个包的长度呢?至少要到第三位长度位才行。我们知道这位之后才知道它后面的内容有多长。
所以在计算包长度这个地方,如果无法判断总包长度的话可返回零。
如果断包它发生在数据长度位之前,比如只收到了两位数据,也就是AABB,那这个时候我们是没有办法判断整个包长度的,只有数据包的长度超过了这个第三位,那就可以知道这个数据包有多长。
因此编写判断条件的逻辑是:如果我拿到的这个数据的长度,它如果小于三的话呢,那我们就返回一个零就好,否则我们就要去找出这段数据里的第三位。
另外由于索引从零开始数的第三位,因此应该再加上前面的三位,那这样的话那我们就计算出来整个包的长度了,这就是非固定长度协议的解包器的配置方法
相关文章
C# 优雅处理通信中的粘包和断包(一) 处理固定长的的协议
C# 优雅处理通信中的粘包和断包(二) 处理非固定长度的协议
C# 优雅处理通信中的粘包和断包(三) 处理使用结束符的协议