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[]

这个流程对于开发来说更方便快捷 嘿嘿