Unity Google Protocol Buffer —— 传输协议

Chinar blog www.chinar.xin

Protocol Buffer


本文提供全流程,中文翻译。

Chinar 的初衷是将一种简单的生活方式带给世人

使有限时间 具备无限可能

Chinar ―― 心分享、心创新!

助力快速完成 Unity 中Protocol Buffer的安装及使用

为新手节省宝贵的时间,避免采坑!

Chinar 教程效果:


文章目录

  • 1
    • Introduce ―― 介绍
      • 1.1 Merit ―― 优点
  • 2
    • Download ―― 下载
  • 3
    • Use ―― 使用
      • 3.1 Find dll ―― 找到 dll
      • 3.1 Support types ―― 支持类型
      • 3.2 Qualifier ―― 修饰符
      • 3.2 Protogen ―― Protogen工具
  • 4
    • Serialize&DeSerialize ―― 序列化和反序列化
      • 4.1 Encapsulation ―― 封装
      • 4.2 Serialize ―― 序列化
      • 4.3 DeSerialize ―― 序列化
  • 5
    • Project ―― 项目文件
  • 支持
    • May Be ―― 开发者,总有一天要做的事!


全文高清图片,点击即可放大观看 (很多人竟然不知道)


1

Introduce ―― 介绍


Protocol Buffers,是Google公司开发的一种数据描述语言,能够将结构化数据序列化,可用于数据存储、通信协议等方面,经常被简称为Protobuf

1.1 Merit ―― 优点

Protobuf是用于结构化数据序列化的方法,和XML、JSON的作用相似,与它们相比protobuf
1. 更简单
2. 数据描述文件大小只是原来的 1/10 至 1/3
3. 解析速度是原来的 20 至 100 倍
4. 减少了二义性
5. 生成了更容易在编程中使用的数据访问类
6. 支持多种编程语言(Java、C++、Python、C#・・・)

你可以定义自己的数据结构,然后使用代码生成器生成的代码来读写这个数据结构


2

Download ―― 下载



protobuf有两个版本,一个是Google官方的版本,名字叫protobuf-csharp

官方网站(科学上网)

Git地址

另一个是社区版名字叫protobuf-net,本章讲解的是社区版的下载和使用

Unity Google Protocol Buffer —— 传输协议_第1张图片NuGet地址

首先打开上面的NuGet网站:
Unity Google Protocol Buffer —— 传输协议_第2张图片
下载下来的文件是nupkg格式的文件,我们需要在VS工程里面安装

新建一个VS工程,选择控制台应用:

点击编辑栏里面的 工具 --> NuGet包管理器 --> 程序包管理器控制台
举个例子
Unity Google Protocol Buffer —— 传输协议_第3张图片
然后会有命令工具弹出
Unity Google Protocol Buffer —— 传输协议_第4张图片
等待命令执行完成
在这里插入图片描述
到此protobuf已安装完毕


3

Use ―― 使用


3.1 Find dll ―― 找到 dll

我们打开解决方案看到已经引用了protobuf-net
Unity Google Protocol Buffer —— 传输协议_第5张图片
然后打开 工程目录–>工程名文件夹–>packages–>protobuf-net.2.4.0–>lib

Unity Google Protocol Buffer —— 传输协议_第6张图片
可以看到有多个版本,我们打开对应工程.Net版本的文件夹,可以看到有protobuf-net.dll文件
Unity Google Protocol Buffer —— 传输协议_第7张图片
保存 protobuf-net.dll 文件,这个文件可以直接放入Unity中使用,也可以在别的工程引用。


3.1 Support types ―― 支持类型

protobuf 支持许多数据类型,我们来看一看

protobuf 数据类型 含义 对应C#类型
bool 布尔类型 bool
double 64位浮点数 double
float 64位浮点数 float
int32 32位整数 int
uint32 无符号32位整数 uint
int64 64位整数 int
uint64 无符号64位整数 uint
string 只能处理 ASCII字符 string
bytes 用于处理多字节的语言字符、如中文 byte
enum 枚举类型 enum
message 可以包含一个自定义的消息类型 object

3.2 Qualifier ―― 修饰符

protobuf的常用修饰符

修饰符 含义
required 不能为空
optional 可选字段,可以为空
repeated repeated 代表这个数据可重复,在C#中为一个List链表

举个例子
我们创建一个后缀为 proto 的文本文件,名字叫Game

syntax = "proto2";//指定版本信息
message USERINFO//用户信息
{
	optional string Account = 1;			//账号
	optional string PassWord = 2;			//密码
	optional string	UserName = 3;	        //用户名
	optional uint32 UserId = 4;			    //用户id
}
message GAMEINFO//游戏信息
{
    repeated USERINFO UserInfo  = 2;//一个用户信息的链表
}

3.2 Protogen ―― Protogen工具

然后我们需要将proto文件生成对应的cs文件,需要一个工具

提取码:xbt4

解压后打开文件夹,我们的proto文件应该放在protos文件夹中,选择run.bat文件,右键编辑
Unity Google Protocol Buffer —— 传输协议_第8张图片
然后会打开一个编辑窗口,里面有一句代码,我们来解析一下这句命令

protogen.exe -i:protos\Game.proto -o:cs\Game.cs -ns:Game

protogen.exe 是我们用到的工具

-i : 后面为输入的文件,可以为多个文件
-o : 输出的文件,只能有一个,如果有多个输入文件,那么会同意输出到这一个文件中
-ns : 输出代码的命名空间

双击运行 run.bat 文件

我们可以在 CS 文件夹中看到生成的 cs 脚本,用 VS 打开

Unity Google Protocol Buffer —— 传输协议_第9张图片

我们再来看看定义的 GAMEINFO 结构
Unity Google Protocol Buffer —— 传输协议_第10张图片
到此,protobuf的书写及转换为指定代码就介绍完成了


4

Serialize&DeSerialize ―― 序列化和反序列化

4.1 Encapsulation ―― 封装

首先我封装了protobuf的序列化与反序列化的代码,使我们的调用更加方便

using System.IO;
using System;

/// 
/// 封装protobuf的序列化与反序列化方法
/// 
/// 
public class ProtoBufSerialize<T>
{
    /// 
    /// 空的构造方法
    /// 
    private ProtoBufSerialize()
    {
    }

    /// 
    /// 将对象序列化为二进制的方法
    /// 
    /// 要序列化的对象
    /// 
    public static byte[] Serialize(T model)
    {
        try
        {
            using (MemoryStream ms = new MemoryStream()) //涉及格式转换,需要用到流,将二进制序列化到流中
            {
                ProtoBuf.Serializer.Serialize<T>(ms, model); //使用ProtoBuf工具的序列化方法

                byte[] result = new byte[ms.Length]; //定义二级制数组,保存序列化后的结果

                ms.Position = 0; //将流的位置设为0,起始点

                ms.Read(result, 0, result.Length); //将流中的内容读取到二进制数组中
                return result;
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine("序列化失败: " + ex.ToString());
            return null;
        }
    }

    /// 
    /// 将二进制消息反序列化成对象
    /// 
    /// 二进制数据
    /// 
    public static T DeSerialize(byte[] msg)
    {
        try
        {
            using (MemoryStream ms = new MemoryStream())
            {
                ms.Write(msg, 0, msg.Length); //将消息写入流中

                ms.Position = 0; //将流的位置归0

                T result = ProtoBuf.Serializer.Deserialize<T>(ms); //使用ProtoBuf工具反序列化对象
                return result;
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine("反序列化失败: " + ex.ToString());
            return default(T);
        }
    }
}

4.2 Serialize ―― 序列化

将我们编译好的Game.cs文件添加进工程中,然后再添加一个测试类 TestProtobuf

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

namespace ProtobufProject
{
    public class TestProtobuf
    {
        /// 
        /// 测试proto序列化
        /// 
        /// 账号
        /// 密码
        /// 用户名
        /// id
        /// 
        public byte[] Write(string account, string password, string name, int id)
        {
            USERINFO userinfo = new USERINFO();
            userinfo.Account  = account;
            userinfo.PassWord = password;
            userinfo.UserName = name;
            userinfo.UserId   = (uint)id;
            byte[] data = ProtoBufSerialize<USERINFO>.Serialize(userinfo);//序列化数据
            return data;
        }

        /// 
        /// 这是一个创建文件的方法
        /// 
        /// 保存文件的路径
        /// 文件的字节数组
        /// 数据长度
        public void CreatFile(string path, byte[] file, int length)
        {
            Stream   sw;
            FileInfo File = new FileInfo(path);
            if (!File.Exists)
            {
                sw = File.Create();
            }
            else
            {
                return;
            }
            sw.Write(file, 0, length);
            sw.Close();
            sw.Dispose();
        }
    }
}

我们在Main方法处写下代码:

static void Main(string[] args)
{
    TestProtobuf testPro = new TestProtobuf();
    byte[] result= testPro.Write("account","123","Chinar",666);//将数据信息传入
    testPro.CreatFile("C:/LY_VS_Project/ProtobufProject/ProtobufProject/Test.txt",result,result.Length);//写入本地
}

然后我们打开Test文件,可以看到序列化的数据:
Unity Google Protocol Buffer —— 传输协议_第11张图片


4.3 DeSerialize ―― 序列化

我们在 TestProtobuf 类中添加一个方法,用来读取本地的文件并返回一个byte数组

        /// 
        /// 读取文件
        /// 
        /// 文件路径
        /// 
        public byte[] ReadFile(string path)
        {
            //读取文件 
            FileStream fs     = File.OpenRead(path);
            byte[]     buffer = new byte[fs.Length];
            fs.Read(buffer, 0, buffer.Length);
            return buffer;
        }

然后我们在Main方法中测试一下

        static void Main(string[] args)
        {
            TestProtobuf testPro = new TestProtobuf();
            //byte[] result= testPro.Write("chinar","123","Chinar",666);
            //testPro.CreatFile("C:/LY_VS_Project/ProtobufProject/ProtobufProject/Test.txt",result,result.Length);

            //读取之前写入本地的数据并反序列化
            USERINFO userinfo = ProtoBufSerialize<USERINFO>.DeSerialize(testPro.ReadFile("C:/LY_VS_Project/ProtobufProject/ProtobufProject/Test.txt"));
            Console.WriteLine(userinfo.Account + "===" + userinfo.PassWord + "===" + userinfo.UserName + "===" + userinfo.UserId);
            Console.ReadKey();
        }

举个例子

Unity Google Protocol Buffer —— 传输协议_第12张图片
测试结果没有问题,以上就是protobuf的序列化与反序列化


5

Project ―― 项目文件



项目文件为 VS 工程:

下载 即可使用
举个例子


支持

May Be ―― 开发者,总有一天要做的事!


拥有自己的服务器,无需再找攻略

Chinar 提供一站式《零》基础教程

使有限时间 具备无限可能!

Chinar 知你所想,予你所求!( Chinar Blog )


Chinar

END

本博客为非营利性个人原创,除部分有明确署名的作品外,所刊登的所有作品的著作权均为本人所拥有,本人保留所有法定权利。违者必究

对于需要复制、转载、链接和传播博客文章或内容的,请及时和本博主进行联系,留言,Email: [email protected]

对于经本博主明确授权和许可使用文章及内容的,使用时请注明文章或内容出处并注明网址

你可能感兴趣的:(Unity,3D,Servers,xml)