Copyright Statement: This article is an original article, please declare when reprinting
I am currently working on a chess and card project, and I need to use socket to transmit protobuf byte stream. I found some blogs and After reading the article, I found that it was not particularly comprehensive, so I took out all the source code I researched and shared it with everyone. Because I just started doing it, there may be shortcomings. Welcome to comment~~
This article is mainly about Serialization and parsing of protocol buffer files, without further ado, let’s go straight to the practical information
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 //将流的位置设为016 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 }
Each message in the protobuf file can be converted into c# through the ProtoGen tool provided by protocol buffer For example,
message Test { required string test1= 1; required string test2= 2; }
will become
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 test216 {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 }
after transformation. Ignore all codes with global, you will find that the transformation The resulting C# class is exactly the same as a standard C# entity class, and these converted classes inherit from ProtoBuf.IExtensible, so the type of the parameters of the serialization function above is IExtensible
with serialization , of course, deserialization is also required, that is, byte[] is deserialized into an object of a type inherited from 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 //将流的位置归014 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 }
Because the deserialized object is inherited from IExtensible Class object, so the return value must be defined using generic constraints, so as to ensure the versatility of the function
After the tool is done, 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
Attached protobuf-net.dll file
Precompilation and conversion tool
The above is the detailed content of Socket transmission protobuf byte stream example tutorial. For more information, please follow other related articles on the PHP Chinese website!