Protobuffer的学习 在C#同序列化一个数据类,和反序列化这数据类取得数据的过程。

版权声明:转载 请说明出处 https://blog.csdn.net/qq2512667/article/details/89517385

在网络传输的过程中 数据会比较多 处理起来会比较麻烦,因此得引入分层的概念,

计算机科学领域的任何问题都可以通过增加一个间接的中间层来解决
“Any problem in computer science can be solved by anther layer of indirection.”

在客服端 和 服务器可以制订一套通信协议, 通信协议是客服端和服务端 共同约定的一个 数据结构,其包含了双方可以发送,并对方可以识别处理的数据包。

Protobuffer 可以把 一个类的实例序列化,和反序列化, 通过反射机制去取得, 开源的。
也支持JsonMap
github源码
2019最新版是 3.7,需要.Net 4.5以上
在这里插入图片描述
API

google 指南

性能比较

protocolbuffer(以下简称PB)是google 的一种数据交换的格式,它独立于语言,独立于平台。google
提供了多种语言的实现:java、c#、c++、go 和
python,每一种实现都包含了相应语言的编译器以及库文件。由于它是一种二进制的格式,比使用 xml
进行数据交换快许多。可以把它用于分布式应用之间的数据通信或者异构环境下的数据交换。作为一种效率和兼容性都很优秀的二进制数据传输格式,可以用于诸如网络传输、配置文件、数据存储等诸多领域。

对一个数据类进行 序列化

项目要添加Pb的引用才可以

using ProtoBuf;
using ProtoBuf.Meta;

    [ProtoContract]
    class NetMode
    {

        [ProtoMember(1)]
        public int id;
        [ProtoMember(2)]
        public string name;
        //如果要使用构造函数,那么 默认构造函数 必须得存在,这个是一个小坑不然会报错
           public NetMode()
        {
        }

        public NetMode(int id,string name)
        {
            this.id = id;
            this.name = name;
        }
    }

如果 数据类不使用构造函数 则不会报错
在这里插入图片描述

Untiy中其实也有序列化特性

不过 Pb 还加了反射技术,因此客服端服务器 两边的数据结构 其实是通用的,不然也用不了Pb,

    [ProtoContract]特性  约定特性,可以用于 类 结构体,枚举,接口

在这里插入图片描述
序列化对象

   /// <summary>
        /// 通过Protobuffer 序列化对象 返回byte[]数组
        /// </summary>
        /// <param name="value"></param>
        /// <returns>二进制数据</returns>
        public static byte[] PBSerialize(object value)
        {
            byte[] data = null;
            //在范围结束时 处理对象
            using (MemoryStream ms=new MemoryStream())
            {
                if (value!=null)
                {
                    // 序列化 到内存里 
                    Serializer.Serialize(ms, value); //此方法 会调用到以下方法. 实际上是同个方法,多层封装
                    RuntimeTypeModel.Default.Serialize(ms, value);
                }
                //设置当前 位置
                ms.Position = 0;
                //写入 数组
                long length = ms.Length;
                data = new byte[length];
                //从内存流中读取  写入到buffer中
                ms.Read(data, 0, (int)length);
                
            }
            return data;
        }
      public static byte[] Serialize(object obj)
        {
            using (var memory = new MemoryStream())
            {
                Serializer.Serialize(memory, obj);  
                return memory.ToArray();
            }
        }

在这里插入图片描述

序列化底层:
在这里插入图片描述

序列化方法, 使用 ProtoWriter 去写进 内存里

在这里插入图片描述
把一个null类型强转为 另一个 类型具体是?
在这里插入图片描述

在这里插入图片描述

序列化 核心部分
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
默认序列化内容。
在这里插入图片描述
获取缓存区。

Interlocked.Exchange: 将对象设置为指定值,并作为原子操作返回对原始对象的引用
如果 原始对象的应用不为null 就返回该缓冲区。

在这里插入图片描述
缓冲池子 大小是20
在这里插入图片描述
释放 缓冲池
在这里插入图片描述

在这里插入图片描述
比较两个对象以获得引用相等性,如果它们相等,则替换其中一个对象、

检查序列化状态,序列化内容在使用后不能更改,如果使用就抛出 throw new InvalidOperationException(“The serialization-context cannot be changed once it is in use”);异常。
在这里插入图片描述

反序列化方法

   public static T Deserialize<T>(byte[] data)
        {
            using (var memory = new MemoryStream(data))
                return Serializer.Deserialize<T>(memory);
        }

        public static T Deserialize<T>(byte[] data, int offset, int size)
        {
            using (var memory = new MemoryStream(data, offset, size))
                return Serializer.Deserialize<T>(memory);
        } 
        
        public static object PBDSerialize( byte[] value ,Type type)
        {
            object o = null;
            using (var memory=new MemoryStream(value))
            {
                o=   RuntimeTypeModel.Default.Deserialize(memory,null, type);
            }
            return o;
        }

猜你喜欢

转载自blog.csdn.net/qq2512667/article/details/89517385