unity Explorer's socket Transmits protobuf Byte Stream (I)

Keywords: C# socket

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

Posted by joshuamd3 on Sun, 23 Jun 2019 12:50:43 -0700