zoukankan      html  css  js  c++  java
  • unity探索者之socket传输protobuf字节流(一)

    版权声明:本文为原创文章,转载请声明http://www.cnblogs.com/unityExplorer/p/6974229.html 

    近期在做一个棋牌项目,需要用到socket传输protobuf字节流,在网上找了一些博客和文章后发现,没有特别全面的,所以把自己研究的全部源码拿出来和大家分享,因为刚开始做,可能会有不足的地方,欢迎拍砖~~

    这一篇主要是protocol buffer文件的序列化和解析,废话不多说了,直接上干货

     1 /// <summary>
     2 /// 将消息序列化为二进制的方法
     3 /// </summary>
     4 /// <param name="model">要序列化的对象</param>
     5 public static byte[] Serialize(IExtensible model)
     6 {
     7   try
     8   {
     9     //创建流对象
    10     MemoryStream ms = new MemoryStream()
    11     //使用ProtoBuf自带的序列化工具序列化IExtensible对象
    12     Serializer.Serialize<IExtensible>(ms, model);
    13     //创建二级制数组,保存序列化后的流
    14     byte[] bytes = new byte[ms.Length];
    15     //将流的位置设为0
    16     ms.Position = 0;
    17     //将流中的内容读取到二进制数组中
    18     ms.Read(bytes, 0, bytes.Length);
    19     return bytes;
    20   }
    21   catch (Exception e)
    22   {
    23     Debug.Log("序列化失败: " + e.ToString());
    24     return null;
    25   }
    26 }

    protobuf文件中的每一条message经过protocol buffer提供的ProtoGen工具可以转成c#的中的类,例如

    message Test {
        required string test1= 1;
        required string test2= 2;
    }

    经过转化后就变成了

     1   [global::System.Serializable, global::ProtoBuf.ProtoContract(Name=@"SedReq")]
     2   public partial class Test : global::ProtoBuf.IExtensible
     3   {
     4     public Test() {}
     5     
     6     private string _test1;
     7     [global::ProtoBuf.ProtoMember(1, IsRequired = true, Name=@"test1", DataFormat = global::ProtoBuf.DataFormat.Default)]
     8     public string test1
     9     {
    10       get { return _test1; }
    11       set { _test1 = value; }
    12     }    
    13     private string _test2;
    14     [global::ProtoBuf.ProtoMember(2, IsRequired = true, Name=@"test2", DataFormat = global::ProtoBuf.DataFormat.Default)]
    15     public string test2
    16     {
    17       get { return _test2; }
    18       set { _test2 = value; }
    19     }
    20     private global::ProtoBuf.IExtension extensionObject;
    21     global::ProtoBuf.IExtension global::ProtoBuf.IExtensible.GetExtensionObject(bool createIfMissing)
    22       { return global::ProtoBuf.Extensible.GetExtensionObject(ref extensionObject, createIfMissing); }
    23   }

    无视所有带global的代码,你会发现,转化后的c#类和一个标准的c#实体类一模一样,并且,这些转化后的类都继承至ProtoBuf.IExtensible,所以上文中的序列化函数的参数的类型是IExtensible

    有了序列化,当然还需要反序列化,也就是讲byte[]反序列化为继承至IExtensible的类型的对象

     1     /// <summary>
     2     /// 将收到的消息反序列化成IExtensible对象
     3     /// </summary>
     4     /// <param name="msg">收到的消息的字节流.</param>
     5     /// <returns></returns>
     6     public static T DeSerialize<T>(byte[] bytes) where T : IExtensible
     7     {
     8         try
     9         {
    10             MemoryStream ms = new MemoryStream()
    11             //将消息写入流中
    12             ms.Write(bytes, 0, bytes.Length);
    13             //将流的位置归0
    14             ms.Position = 0;
    15             //反序列化对象
    16             T result = Serializer.Deserialize<T>(ms);
    17             return result;
    18         }
    19         catch (Exception e)
    20         {
    21             Debug.Log("反序列化失败: " + e.ToString());
    22             return null;
    23         }
    24     }

    因为反序列化后的对象是继承至IExtensible的类的对象,所以返回值必须使用泛型约束来定义,这样才能保证函数的通用性

    工具搞定,接下来就是测试代码了

    1     public void Test()
    2     {
    3         Test test = new Test() { test1 = "123", test2 = "456" };
    4         byte[] bytes = Serialize(test);
    5         Test test2 = DeSerialize<Test>(bytes);
    6         Debug.Log(test2.test1 + test2.test2);
    7     }

    输出结果  123456

    附上protobuf-net.dll文件

    https://files.cnblogs.com/files/unityExplorer/protobuf-net.zip

    预编译和转化工具

    https://files.cnblogs.com/files/unityExplorer/protoGen.zip

    由于环境不同关系,并非所有的博客内容都会上传完整的源码,大部分的源码,大家可以到我的github主页上的UGCFramework查找

    传送门:https://github.com/wulonghao/UGCFramework
  • 相关阅读:
    Spring MVC的Controller统一异常处理:HandlerExceptionResolver
    Log4j按级别输出日志到不同文件配置
    Linux top命令用法
    free -m内存使用详解
    Linux运维中遇到的常见问题
    ubuntu16.04 nginx安装
    redis主从配置及主从切换
    Redis持久化配置-AOF
    如何处理消极想法
    libevent安装总结
  • 原文地址:https://www.cnblogs.com/unityExplorer/p/6974229.html
Copyright © 2011-2022 走看看