Recently, in a chess and card project, we need to use socket to transmit protobuf byte stream. After searching some blogs and articles on the Internet, we found that there is no particular comprehensive, so we can share all the source code of our research with you. Because we have just started, there may be some shortcomings. Welcome to pat bricks.~~
This article is mainly about the serialization and parsing of protocol buffer files, not to mention much nonsense, go straight to dry goods.
1 /// <summary> 2 /// Method of serializing messages into binary 3 /// </summary> 4 /// <param name="model">Objects to serialize</param> 5 public static byte[] Serialize(IExtensible model) 6 { 7 try 8 { 9 //Create stream objects 10 MemoryStream ms = new MemoryStream() 11 //Use ProtoBuf Serialization of built-in serialization tools IExtensible object 12 Serializer.Serialize<IExtensible>(ms, model); 13 //Create a secondary array to save the serialized stream 14 byte[] bytes = new byte[ms.Length]; 15 //Set the position of the flow to 0 16 ms.Position = 0; 17 //Read the contents of the stream into a binary array 18 ms.Read(bytes, 0, bytes.Length); 19 return bytes; 20 } 21 catch (Exception e) 22 { 23 Debug.Log("Serialization failure: " + e.ToString()); 24 return null; 25 } 26 }
Each message in the protobuf file can be converted to a class in c # through the ProtoGen tool provided by protocol buffer, such as
message Test { required string test1= 1; required string test2= 2; }
After transformation, it becomes
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 }
Ignoring all the code with global, you will find that the converted c # class is exactly the same as a standard c # entity class, and these transformed classes inherit to ProtoBuf.IExtensible, so the parameter type of the serialized function in the above is IExtensible.
With serialization, of course, deserialization is also required, that is, byte [] deserialized into objects of type inherited to IExtensible
1 /// <summary> 2 /// Deserialize received messages into IExtensible object 3 /// </summary> 4 /// <param name="msg">Byte stream of received message.</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 //Write messages into the stream 12 ms.Write(bytes, 0, bytes.Length); 13 //Position the stream to 0 14 ms.Position = 0; 15 //Deserialized object 16 T result = Serializer.Deserialize<T>(ms); 17 return result; 18 } 19 catch (Exception e) 20 { 21 Debug.Log("Deserialization failure: " + e.ToString()); 22 return null; 23 } 24 }
Because the deserialized object is an object inherited from the IExtensible class, the return value must be defined with generic constraints in order to guarantee the universality of the function.
The tool is done, and the next step is to test the code.
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 }
Output result 123456
Attach the protobuf-net.dll file
http://files.cnblogs.com/files/unityExplorer/protobuf-net.zip
Pre-compiler and transformation tools
http://files.cnblogs.com/files/unityExplorer/protoGen.zip