C#语言服务器和开发准备(一)Protobuf的学习

版权声明:未经同意,请勿转载 https://blog.csdn.net/qq_25542475/article/details/86765583
本章主要讲述C#服务器开发中使用的序列化与反序列化工具protobuf的使用。

一 Protobuf介绍

(一)Protobuf简介

Google Protocol Buffer( 简称 Protobuf) 是 Google 公司内部的混合语言数据标准,目前已经正在使用的有超过 48,162 种报文格式定义和超过 12,183 个 .proto 文件。他们用于 RPC 系统和持续数据存储系统。
Protocol Buffers 是一种轻便高效的结构化数据存储格式,可以用于结构化数据串行化,或者说序列化。它很适合做数据存储或 RPC 数据交换格式。可用于通讯协议、数据存储等领域的语言无关、平台无关、可扩展的序列化结构数据格式。目前提供了 C++,Java,Python和C#等语言的 API。

(二)Protobuf的特点

在这里插入图片描述

(三)Protobuf语法规则

(1)指定字段类型
所有的字段都有标量类型:string,bool等等,当然,你也可以为字段指定其他的合成类型,包括枚举或其他消息类型。
(2)分配标识号
在消息定义中,每个字段都有唯一的一个标识号,这些标识号是用来在消息的二进制格式中识别各个字段,一旦开始使用就不能修改。
!注:[1,15]之内的标识号在编码的时候会占用一个字节,[16,2047]之内的标识号则占用两个字节,所以频繁使用的元素使用[1,15]之内的标识号。
!切记:要为将来有可能使用的元素预留一些标识号。最小的标识号从1开始,最大的到229-1即536,870,911,不可以使用19000-19999的标识号,Protobuf协议中对这些标识号进行了预留,如果使用,编译时就会报错。
(3)指定字段规则
所指定的消息字段修饰符必须如下之一:
*required:不可增加或删除的字段,必须初始化。
*optional:可选字段,可删除,可以不初始化。
*repeated:可重复字段(对应C#里面的list)。
(4)标量数值类型
一个标量消息字段可以含有一个如下的类型,该表格展示.proto文件中的类型以及与之对应的,在自动生成的访问类中的类型:
在这里插入图片描述
(5)添加注释
向proto文件添加注释,也跟C#语法一样(//),如:
protoTest.proto

syntax="proto2";
message SearchRequest
{
   required string query=1[default="hahhah"];//默认值放在default
}

(6)枚举
protoTest.proto

syntax="proto2";
message SearchRequest
{
  // required string query=1[default="hahhah"];//默认值放在default
  enum Person{
    AGE=0;
	NAME=1;
	SEX=2;
  }
}

(7)嵌套类型
protoTest.proto

syntax="proto2";
package Cmd;//相当于命名空间
message SearchRequest
{
  required string query=1[default="hahhah"];//默认值放在default
  enum Person{
    AGE=0;
 	NAME=1;
 	SEX=2;
  }
  message Model
  {
     required string Line1=1;
	 required string Line2=2;
  }
}

(8)引用
protoTest1.proto

syntax="proto2";
package Cmd;
import "protoTest.proto";
message Test
{
  optional SearchRequest searchRequest=1;
}

(四)Protobuf-net下载地址

下载地址

(五)Protobuf编译cs文件

(1)解压下载的压缩包,找到protobuf-net-master\src\protogen.site\wwwroot\protogen文件下的protogen各版本压缩包。我们能够借助protogen将.proto转换为.cs文件。从中选择一个版本解压缩,解压后在加压的文件下的net46文件夹下新建c#和proto两个文件夹,将刚才创建的两个protoTest.proto和prototest1.proto复制到proto文件夹下。
在这里插入图片描述
(2)运行命令行,先cd到protogen.exe所在的文件夹,然后输入protogen.exe --proto_path=./proto --csharp_out=./c# protoTest1.proto,其中–proto_path=./proto指定要编译的文件目录,–csharp_out=./c#指定编译结束后输出目录,protoTest1.proto指示要编译的文件。
在这里插入图片描述
当输出generated: ./c#\protoTest1.cs说明编译成功,可以查看到c#文件加下生成了一个protoTest1.cs文件。

二 利用Protobuf进行序列化与反序列化

VS C#控制台程序 

(1)模板 Person.cs(通过Protogen.exe编译出来的.cs文件)

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using ProtoBuf;

namespace ProtoTest
{
    [ProtoContract]//在需要序列花的类签名上面加上[ProtoContract]
    class Person
    {
        [ProtoMember(1)]//在类的字段签名上加[ProtoMeber(i)]每个都加括号的数字增加
        public string Name { get; set; }
        [ProtoMember(2)]
        public int age { get; set; }
        [ProtoMember(3)]
        public int weight { get; set; }
        public override string ToString()
        {
            return "Name:" + Name + "," + "age:" + age + "," + "weight:" + weight;
        }
    }
}

(2)ProtobufHelper.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO;

namespace ProtoTest
{
    class ProtobufHelper
    {
        /// <summary>
        /// 序列化为string
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="t"></param>
        /// <returns></returns>
        public static string Serialize<T>(T t)
        {
            using (MemoryStream ms = new MemoryStream())
            {
                Serializer.Serialize<T>(ms, t);
                return Encoding.UTF8.GetString(ms.ToArray());
            }
        }
        /// <summary>
        /// 序列化到文件
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="path"></param>
        /// <param name="t"></param>
        public static void Serialize<T>(string path, T t)
        {
            using (Stream file = File.Create(path))
            {
                Serializer.Serialize<T>(file, t);
            }
        }
        /// <summary>
        /// 字符串反序列化对象
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="content"></param>
        /// <returns></returns>
        public static T DeSerialize<T>(string content)
        {
            using (MemoryStream ms = new MemoryStream(Encoding.UTF8.GetBytes(content)))
            {
                T t = Serializer.Deserialize<T>(ms);
                return t;
            }
        }
        /// <summary>
        /// 文件反序列化对象
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="filestream"></param>
        /// <returns></returns>
        public static T DeSerialize<T>(Stream filestream)
        {
            return Serializer.Deserialize<T>(filestream);
        }
    }
}

(3)Program.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO;

namespace ProtoTest
{
    class Program
    {
        static void Main(string[] args)
        {
            Person one = new Person() { Name = "A", age = 18,weight=40};
            Person two = new Person() { Name = "B", age = 15,weight=44};
            List<Person> people = new List<Person>() { one, two };
            //序列化字符
            string temp = ProtobufHelper.Serialize<List<Person>>(people);
            //序列化到文件
            ProtobufHelper.Serialize<List<Person>>("Test.txt",people);
            Console.WriteLine(temp);
            //反序列化字符
            List<Person> newlist=ProtobufHelper.DeSerialize<List<Person>>(temp);
            for (int i = 0; i < newlist.Count; i++)
            {
                Console.WriteLine(newlist[i].ToString());
            }
            //反序列化字符
            List<Person> newlist1 = ProtobufHelper.DeSerialize<List<Person>>(new FileInfo("Test.txt").OpenRead());
            for (int i = 0; i < newlist1.Count; i++)
            {
                Console.WriteLine(newlist1[i].ToString());
            }
            while (true)
            { }
        }
    }
}

猜你喜欢

转载自blog.csdn.net/qq_25542475/article/details/86765583