Unity Google Protocol Buffer —— 传输协议

14 篇文章 2 订阅
5 篇文章 1 订阅

Chinar blog www.chinar.xin

Protocol Buffer


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

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

使有限时间 具备无限可能

Chinar ―― 心分享、心创新!

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

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

Chinar 教程效果:



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


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,本章讲解的是社区版的下载和使用

NuGet地址

首先打开上面的NuGet网站:
在这里插入图片描述
下载下来的文件是nupkg格式的文件,我们需要在VS工程里面安装

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

点击编辑栏里面的 工具 --> NuGet包管理器 --> 程序包管理器控制台
举个例子
在这里插入图片描述
然后会有命令工具弹出
在这里插入图片描述
等待命令执行完成
在这里插入图片描述
到此protobuf已安装完毕


3

Use ―― 使用


3.1 Find dll ―― 找到 dll

我们打开解决方案看到已经引用了protobuf-net
在这里插入图片描述
然后打开 工程目录–>工程名文件夹–>packages–>protobuf-net.2.4.0–>lib

在这里插入图片描述
可以看到有多个版本,我们打开对应工程.Net版本的文件夹,可以看到有protobuf-net.dll文件
在这里插入图片描述
保存 protobuf-net.dll 文件,这个文件可以直接放入Unity中使用,也可以在别的工程引用。


3.1 Support types ―― 支持类型

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

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

3.2 Qualifier ―― 修饰符

protobuf的常用修饰符

修饰符含义
required不能为空
optional可选字段,可以为空
repeatedrepeated 代表这个数据可重复,在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文件,右键编辑
在这里插入图片描述
然后会打开一个编辑窗口,里面有一句代码,我们来解析一下这句命令

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

protogen.exe 是我们用到的工具

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

双击运行 run.bat 文件

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

在这里插入图片描述

我们再来看看定义的 GAMEINFO 结构
在这里插入图片描述
到此,protobuf的书写及转换为指定代码就介绍完成了


4

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

4.1 Encapsulation ―― 封装

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

using System.IO;
using System;

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

    /// <summary>
    /// 将对象序列化为二进制的方法
    /// </summary>
    /// <param name="model">要序列化的对象</param>
    /// <returns></returns>
    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;
        }
    }

    /// <summary>
    /// 将二进制消息反序列化成对象
    /// </summary>
    /// <param name="msg">二进制数据</param>
    /// <returns></returns>
    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
    {
        /// <summary>
        /// 测试proto序列化
        /// </summary>
        /// <param name="account">账号</param>
        /// <param name="password">密码</param>
        /// <param name="name">用户名</param>
        /// <param name="id">id</param>
        /// <returns></returns>
        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;
        }

        /// <summary>
        /// 这是一个创建文件的方法
        /// </summary>
        /// <param name="path">保存文件的路径</param>
        /// <param name="file">文件的字节数组</param>
        /// <param name="length">数据长度</param>
        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文件,可以看到序列化的数据:
在这里插入图片描述


4.3 DeSerialize ―― 序列化

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

        /// <summary>
        /// 读取文件
        /// </summary>
        /// <param name="path">文件路径</param>
        /// <returns></returns>
        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();
        }

举个例子

在这里插入图片描述
测试结果没有问题,以上就是protobuf的序列化与反序列化


5

Project ―― 项目文件



项目文件为 VS 工程:

下载 即可使用
举个例子


支持

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


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

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

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

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


Chinar

END

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

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

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

  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值