Copyright Notice:This article is original article, reprint please declare
Recently in a chess project, need to use the socket to transmit PROTOBUF byte stream, find some blog and articles on the internet found that there is no special comprehensive, so the full source of their own research to take out and everyone to share, because just started to do, there may be insufficient places, welcome to shoot Bricks ~ ~
This article is mainly protocol buffer file serialization and parsing, nonsense not much to say, directly on the dry
1//<summary> 2////To serialize the message to a binary method 3///</summary> 4//<param name= "Model" > object to serialize </param> 5 p Ublic Static byte[] Serialize (iextensible model) 6 {7 Try 8 {9//Create stream object Ten MemoryStream ms = new MemoryStream ( ) 11//Serialize Iextensible object using Protobuf's own serialization tool serializer.serialize<iextensible> (MS, model); 13//Create two-level array, save order The serialized stream byte[] bytes = new Byte[ms. LENGTH];15//The position of the stream is set to 016 Ms. Position = 0;17//reads the contents of the stream into a binary array of Ms. Read (bytes, 0, bytes. Length), return bytes;20}21 catch (Exception E) ("Serialization failed:" + e.tostring ()), {Debug.Log Ull;25}26}
Each message in the Protobuf file passes through the Protogen tool provided by protocol buffer, which can be turned into a class in C #, for example
Message Test { Required String test1= 1; Required String test2= 2;}
After the transformation, it becomes
1 [global::system.serializable, Global::P rotobuf.protocontract (name=@ "Sedreq")] 2 public partial class Test:global: :P rotobuf.iextensible 3 {4 public Test () {} 5 6 private string _test1; 7 [Global::P Rotobuf.protomember (1, IsRequired = True, name=@ "test1", DataFormat = global::P rotoBuf.DataFormat.Default)] 8 public string Test1 9 {Ten get {return _test1;} One set {_test1 = value;} The private string _test2;14 [global::P rotobuf.protomember (2, isrequired = True, name=@ "Test2", datafor Mat = global::P rotoBuf.DataFormat.Default)]15 public string test216 {get {return _test2;} set {_test2 = value;} }20 Private Global::P rotobuf.iextension extensionobject;21 Global::P rotobuf.iextension Global::P ROTOBUF.IEX Tensible. Getextensionobject (bool createifmissing) {return global::P rotoBuf.Extensible.GetExtensionObject (ref extensionobj ECT, createifmissing); }23}
Ignoring all the code with global, you'll find that the converted C # class is exactly the same as a standard C # entity class, and that these transformed classes inherit to protobuf.iextensible, so the type of the arguments to the serialization function above is iextensible
With serialization, of course, deserialization is also required, that is, byte[] deserialized to an object of type inherited to Iextensible
1//<summary> 2/// to deserialize the received message into a Iextensible object 3// </summary> 4// <param name= "MSG" > The byte stream of the message received .</param> 5 //<returns></returns> 6 public static T deserialize<t> ( Byte[] bytes) where t:iextensible 7 {8 try 9 {Ten MemoryStream ms = new MemoryStream () one //write message to stream 1 2 Ms. Write (bytes, 0, bytes. Length), and/ /the position of the stream is attributed to 014 Ms. Position = 0;15 //Deserialization Object- T result = serializer.deserialize<t> (ms); + return result;18 } (Exception e) { Debug.Log ("Deserialization failed:" + e.tostring ()); return null;23 }24 }
Because the deserialized object is an object of a class that inherits to Iextensible, the return value must be defined using a generic constraint to ensure the versatility of the function
The tools are done, and then the code is tested.
1 public Void Test () 2 {3 test test = new Test () {test1 = "123", test2 = "456"};4 byte[] bytes = Serializ E (test); 5 Test test2 = deserialize<test> (bytes); 6 Debug.Log (Test2.test1 + test2.test2); 7 }
Output Results 123456
Attach Protobuf-net.dll file
Pre-compilation and conversion tools