Socket 高效拆解包
public class MarshalEndian
{
private readonly int ConstLength = 12; //最小包长
private List<byte> leftBytes = new List<byte>(); //历史遗留包数据
private readonly byte head1 = 0x1F; //自定义头1
private readonly byte head2 = 0xF2; //自定义头2
private readonly byte foot1 = 0x0A; //自定义尾1
private readonly byte foot2 = 0x0D; //自定义尾2
public byte[] Encode(SocketPackage msg)
{
var buffer = new List<byte>();
buffer.Add(head1);
buffer.Add(head2);
//将包类型 转换为 byte 数组 tobytes 需要自己编写
var arry = msg.toBytes();
buffer.AddRange(arry);
buffer.Add(foot1);
buffer.Add(foot2);
return buffer.ToArray();
}
public List<SocketPackage> GetSendSockets(byte[] buffer, int len)
{
//拷贝当前有效数据
var bytes = new byte[len];
Buffer.BlockCopy(buffer, 0, bytes, 0, len);
//合并上个包的遗留数据
if (leftBytes.Count > 0)
{
leftBytes.AddRange(bytes);
bytes = leftBytes.ToArray();
leftBytes.Clear();
leftBytes = new List<byte>();
}
var sendSockets = new List<SocketPackage>();
while (bytes.Length > 0 || leftBytes.Count > 0)
{
if (bytes.Length < ConstLength)
{
leftBytes.AddRange(bytes);
return sendSockets;
}
//寻找head1的索引
var isFind = false;
var headIndex = 0;
while (headIndex < bytes.Length)
{
if (bytes[headIndex] == head1 && bytes[headIndex + 1] == head2)
{
isFind = true;
break;
}
headIndex++;
isFind = false;
}
if (!isFind)
{
leftBytes.AddRange(bytes);
return sendSockets;
}
//寻找foot1的索引
var footIndex = headIndex;
while (footIndex < bytes.Length)
{
if (bytes[footIndex] == foot1 && bytes[footIndex + 1] == foot2)
{
isFind = true;
break;
}
footIndex++;
isFind = false;
}
if (!isFind || (footIndex - headIndex + 2) < ConstLength)
{
leftBytes.AddRange(bytes);
return sendSockets;
}
//提取一个完整包数据 并解析
var packBuffer = bytes.Skip(headIndex).Take(footIndex + 2).ToList();
var packBytes = packBuffer.Skip(2).Take(packBuffer.Count - 4).ToArray();
//将byte数组转为数据实体 Convert.toPack 是我随便写的一个方法
var sendSocket = Convert.toPack(packBytes);
sendSockets.Add(sendSocket);
//留存剩余的包数据
leftBytes = bytes.ToList();
leftBytes.RemoveRange(headIndex, packBuffer.Count);
bytes = new byte[0];
}
return sendSockets;
}
public void Dispose()
{
this.Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool flag)
{
if (flag)
{
IDisposable disposable = this.leftBytes as IDisposable;
if (disposable != null) { disposable.Dispose(); }
}
}
}
SocketPackage 是我定义的包实体类型
SocketPackage.toBytes 和 Convert.toPack 分别对应将实体类与byte数组的互转方法
注意事项:
一个Socket 对应一个 MarshalEndian
参考实例: marshalsDict 是服务器端的一个字典 key 为Socket ;value 为 MarshalEndian

最后值得一提的是 如果还没有定义如何打包和解包
可以试试 model <--> json <--> byte[]
这个流程对于开发来说更方便快捷 嘿嘿