0006-异步编程协议初识protobuf-net

在我们编程的时候我们不仅仅要对一个字符串作为信息传输,有时候可能要将一个对象的相关信息进行传输,比如名字,分数,等级,位置,旋转等信息进行传输。分开传递工作量可能比较大。我们就可以考虑是不是可以将一个对象整体尽心传输。
protobuf是google的一个开源项目,protobuf可以很方便的将一个对象进行序列化,而且相对来说体积较小。 
源代码下载地址:https://github.com/mgravell/protobuf-net
开源项目地址如下:https://code.google.com/p/protobuf-net/ ,下载解压后的目录如下所示,每个文件夹的详细介绍都在最后一个txt文件里面了。
在这里插入图片描述
ProtoGen是用来根据***.proto文件生成对应的***.cs文件的。
.proto可以直接通过记事本编写。

基本语法:

一 基本说明

结构定义文件为.proto,
可以使用import包含另一个.proto文件,
注释使用//
package 命名空间
message 类

二 语法

字段限制

required: 必须赋值的字符
optional: 可有可无的字段,可以使用[default = xxx]配置默认值
repeated: 可重复变长字段,类似数组

tag

每个字段都有独一无二的tag
tag 1-15是字节编码,16-2047使用2字节编码,所以1-15给频繁使用的字段

类型

在这里插入图片描述系统默认值:
string默认为空字符串;
bool默认为false;
数值默认为0;
enum默认为第一个元素

enum PhoneType { // 定义枚举类型,生成Person_PhoneType类型
MOBILE = 0;
HOME = 1;
WORK = 2;
}
proto文件示例

syntax = "proto2"; // 定义语法类型,通常proto3好于proto2,proto2好于proto1

package tutorial; // 定义作用域

message Person {        // 生成类class Person : public ::google::protobuf::Message 
  required string name = 1;
  required int32 id = 2;
  optional string email = 3;

  enum PhoneType { // 定义枚举类型,生成Person_PhoneType类型
    MOBILE = 0;
    HOME = 1;
    WORK = 2;
  }

  message PhoneNumber { // 生成Person_PhoneNumber类
    required string number = 1;
    optional PhoneType type = 2 [default = HOME]; // 值必须是枚举类型中的一个
  }
  repeated PhoneNumber phones = 4;
}

message AddressBook {
  repeated Person people = 1;
}

以下是protogen工具,使用此工具可以很方便的将.proto文件转化成cs文件
在这里插入图片描述使用命令可以通过cmd执行protogen.exe得到相关执行命令
在这里插入图片描述例如:
在这里插入图片描述生成单个文件比较简单
如果是多个文件的话执行可能相对麻烦,我们可以使用批处理

@echo off
 
::协议文件路径, 最后不要跟“\”符号
set SOURCE_FOLDER=D:\CodesStorage\UnityPrejects\YYSever\ServerProtocol\Sources
 
::C#编译器路径
set CS_COMPILER_PATH=E:\SoftWares\WorkSofts\protogen\protogen.exe
::C#文件生成路径, 最后不要跟“\”符号
set CS_TARGET_PATH=D:\CodesStorage\UnityPrejects\YYSever\ServerProtocol\Protocols

 
::删除之前创建的文件
del %CS_TARGET_PATH%\*.* /f /s /q
 
::遍历所有文件
for /f %%i in ('dir /b "%SOURCE_FOLDER%\*.proto"') do (
     
     ::生成 C# 代码
     echo %CS_COMPILER_PATH% -i:%%i -o:%CS_TARGET_PATH%\%%~ni.cs
     %CS_COMPILER_PATH% -i:%%i -o:%CS_TARGET_PATH%\%%~ni.cs
)
 
echo Tell You Created Protoccl Success!!
 
pause

以上工作完毕之后,我们可以测试相关此工具了。
测试:
proto文件

package ServerProtocol.Protocols;
message Student
{
	required string name = 1;
	optional int32 id = 2;
	repeated string email = 3;
	//枚举类型
	enum PhoneType{
		Mobile = 0;
		Home = 1;
		Work = 2;
	}	
	message PhoneNumber {
	    required string number = 1;
	    optional PhoneType type = 2 [default = Home];
	}
	repeated PhoneNumber phone = 4;
}

生成cs文件

//------------------------------------------------------------------------------
// <auto-generated>
//     This code was generated by a tool.
//
//     Changes to this file may cause incorrect behavior and will be lost if
//     the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------

// Generated from: Student.proto
namespace ServerProtocol.Protocols
{
  [global::System.Serializable, global::ProtoBuf.ProtoContract(Name=@"Student")]
  public partial class Student : global::ProtoBuf.IExtensible
  {
    public Student() {}
    
    private string _name;
    [global::ProtoBuf.ProtoMember(1, IsRequired = true, Name=@"name", DataFormat = global::ProtoBuf.DataFormat.Default)]
    public string name
    {
      get { return _name; }
      set { _name = value; }
    }
    private int _id = default(int);
    [global::ProtoBuf.ProtoMember(2, IsRequired = false, Name=@"id", DataFormat = global::ProtoBuf.DataFormat.TwosComplement)]
    [global::System.ComponentModel.DefaultValue(default(int))]
    public int id
    {
      get { return _id; }
      set { _id = value; }
    }
    private readonly global::System.Collections.Generic.List<string> _email = new global::System.Collections.Generic.List<string>();
    [global::ProtoBuf.ProtoMember(3, Name=@"email", DataFormat = global::ProtoBuf.DataFormat.Default)]
    public global::System.Collections.Generic.List<string> email
    {
      get { return _email; }
    }
  
    private readonly global::System.Collections.Generic.List<ServerProtocol.Protocols.Student.PhoneNumber> _phone = new global::System.Collections.Generic.List<ServerProtocol.Protocols.Student.PhoneNumber>();
    [global::ProtoBuf.ProtoMember(4, Name=@"phone", DataFormat = global::ProtoBuf.DataFormat.Default)]
    public global::System.Collections.Generic.List<ServerProtocol.Protocols.Student.PhoneNumber> phone
    {
      get { return _phone; }
    }
  
  [global::System.Serializable, global::ProtoBuf.ProtoContract(Name=@"PhoneNumber")]
  public partial class PhoneNumber : global::ProtoBuf.IExtensible
  {
    public PhoneNumber() {}
    
    private string _number;
    [global::ProtoBuf.ProtoMember(1, IsRequired = true, Name=@"number", DataFormat = global::ProtoBuf.DataFormat.Default)]
    public string number
    {
      get { return _number; }
      set { _number = value; }
    }
    private ServerProtocol.Protocols.Student.PhoneType _type = ServerProtocol.Protocols.Student.PhoneType.Home;
    [global::ProtoBuf.ProtoMember(2, IsRequired = false, Name=@"type", DataFormat = global::ProtoBuf.DataFormat.TwosComplement)]
    [global::System.ComponentModel.DefaultValue(ServerProtocol.Protocols.Student.PhoneType.Home)]
    public ServerProtocol.Protocols.Student.PhoneType type
    {
      get { return _type; }
      set { _type = value; }
    }
    private global::ProtoBuf.IExtension extensionObject;
    global::ProtoBuf.IExtension global::ProtoBuf.IExtensible.GetExtensionObject(bool createIfMissing)
      { return global::ProtoBuf.Extensible.GetExtensionObject(ref extensionObject, createIfMissing); }
  }
  
    [global::ProtoBuf.ProtoContract(Name=@"PhoneType")]
    public enum PhoneType
    {
            
      [global::ProtoBuf.ProtoEnum(Name=@"Mobile", Value=0)]
      Mobile = 0,
            
      [global::ProtoBuf.ProtoEnum(Name=@"Home", Value=1)]
      Home = 1,
            
      [global::ProtoBuf.ProtoEnum(Name=@"Work", Value=2)]
      Work = 2
    }
  
    private global::ProtoBuf.IExtension extensionObject;
    global::ProtoBuf.IExtension global::ProtoBuf.IExtensible.GetExtensionObject(bool createIfMissing)
      { return global::ProtoBuf.Extensible.GetExtensionObject(ref extensionObject, createIfMissing); }
  }
}

编写类

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using ProtoBuf;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;

namespace ServerProtocol
{
    public class TestStudent
    {
        /// <summary>
        /// 序列化对象
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="t"></param>
        /// <returns></returns>
        public byte[] SerializeStudent<T>(T t) where T:class
        {

            using (MemoryStream ms = new MemoryStream())
            {
                Serializer.Serialize<T>(ms, t);
                return ms.ToArray();
            }
        }
        /// <summary>
        /// 反序列化对象
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="arr"></param>
        /// <returns></returns>
        public T DeserializeStudent<T>(byte[] arr) where T : class
        {

            using (MemoryStream ms = new MemoryStream(arr))
            {
                return Serializer.Deserialize<T>(ms);
            }
        }
    }
}

测试代码

        static void Main(string[] args)
        {
            Student s = new Student();
            s.name = "abc";

            TestStudent test = new TestStudent();
            byte[] arr = test.SerializeStudent<Student>(s);

            Student st = test.DeserializeStudent<Student>(arr);
            Console.WriteLine(st.name);
            
        }

运行结果
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

yy763496668

您的鼓励是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值