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文件

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

預編譯和轉化工具

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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM