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 ///methods for serializing messages into binary3 /// </summary>4 /// <param name= "model" >the object to serialize</param>5 Public Static byte[] Serialize (iextensible model)6 {7 Try8 {9 //creating a Stream objectTenMemoryStream ms =NewMemoryStream () One //serializing Iextensible objects using Protobuf's own serialization tool ASerializer.serialize<iextensible>(MS, model); - //create a two-level array to hold the serialized stream - byte[] bytes =New byte[Ms. Length]; the //set the position of the stream to 0 -Ms. Position =0; - //reads the contents of a stream into a binary array -Ms. Read (Bytes,0, Bytes. Length); + returnbytes; - } + Catch(Exception e) A { atDebug.Log ("Serialization failed:"+e.tostring ()); - return NULL; - } -}
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 { string1; string 2 ;}
After the transformation, it becomes
1[Global:: System.serializable,Global::P rotobuf.protocontract (name=@"Sedreq")]2 Public Partial classTest:Global::P rotobuf.iextensible3 {4 PublicTest () {}5 6 Private string_test1;7[Global::P Rotobuf.protomember (1, isrequired =true, name=@"test1", DataFormat =Global::P rotoBuf.DataFormat.Default)]8 Public stringtest19 {Ten Get{return_test1;} One Set{_test1 =value;} A } - Private string_test2; -[Global::P Rotobuf.protomember (2, isrequired =true, name=@"test2", DataFormat =Global::P rotoBuf.DataFormat.Default)] the Public stringtest2 - { - Get{return_test2;} - Set{_test2 =value;} + } - Private Global::P rotobuf.iextension extensionobject; + Global::P rotobuf.iextensionGlobal::P RotoBuf.IExtensible.GetExtensionObject (BOOLcreateifmissing) A{return Global::P RotoBuf.Extensible.GetExtensionObject (refExtensionobject, createifmissing); } at}
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 ///deserializes the received message into a Iextensible object3 /// </summary>4 /// <param name= "MSG" >The byte stream of the received message.</param>5 /// <returns></returns>6 Public StaticT deserialize<t> (byte[] bytes)wheret:iextensible7 {8 Try9 {TenMemoryStream ms =NewMemoryStream () One //writes a message to the stream AMs. Write (Bytes,0, Bytes. Length); - //return the position of the stream to 0 -Ms. Position =0; the //deserializing Objects -T result = serializer.deserialize<t>(MS); - returnresult; - } + Catch(Exception e) - { +Debug.Log ("deserialization failed:"+e.tostring ()); A return NULL; at } -}
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 voidTest ()2 {3Test test =NewTest () {test1 ="123", test2 ="456" };4 byte[] bytes =Serialize (test);5Test test2 = deserialize<test>(bytes);6Debug.Log (Test2.test1 +test2.test2);7}
Output Results 123456
Attach Protobuf-net.dll file
Http://files.cnblogs.com/files/unityExplorer/protobuf-net.zip
Pre-compilation and conversion tools
Http://files.cnblogs.com/files/unityExplorer/protoGen.zip
Unity Explorer's socket transfer protobuf byte stream (i)