使用的xml,json不是挺好的吗?为什么要用这个东西? 首先我们来了解一下protobuf这个东西吧!
要知道Protobuf是google的一个开源项目 那么他能用来干什么呢?1.数据存储(序列化和反序列化),这个功能类似xml和json等;2.制作网络通信协议; 既然是开源项目,那么我们就可以去github上面去下载下来研究。GitHub上面链接地址
为什么要使用protobuf呢? Protobuf 全称Protocol Buffers 是一种轻便高效的结构化数据存储格式,可以用于结构化数据串行化,很适合做数据存储或 RPC 数据交换格式。它可用于通讯协议、数据存储等领域的语言无关、平台无关、可扩展的序列化结构数据格式。目前提供了 C++、Java、Python、C#等多种语言的 API。Protobuf是google开源的序列化和反序列化工具,主要是用在网络游戏的消息结构体定义上。它相对于XML文件和Json文件性能更好,效率更高。所以我们使用protubuf啦!
protobuf的基本语言格式了。里面有一些关键字
message People { required string name = 1; required int32 id = 2; optional string email = 3;
enum Sex { MAN = 0; WOMAN = 1; }
message QQNumber
{ required string number = 1; optional Sex sex = 2 [default = MAN]; }
repeated QQNumber qq = 4;
}
定义声明:required:声明该字段是必填字段。对应类的属性optional:声明该字段是可选字段。创建一个具有默认值的属性,通过[default=XXX]设置默认值,不添加默认为空置。如string默认为“”,int默认为0repeated:声明该字段是可重复字段,通常用数组表示,也可以是c#语言中的list集合。enum 创建枚举message 创建自定义类或内部类
一般游戏主要使用protobuf来作为网络通讯的协议来传输的,下面我们来讨论一下如何设计这个通讯协议呢?
首先我们要有两个必要的数据:协议号和协议类型,将这两个数据分别存储起来
当客户端向服务器发送数据时,会根据协议类型加上协议号,然后使用protobuf序列化之后再发送给服务器;当服务器发送数据给客户端时,根据协议号,用protobuf根据协议类型反序列化数据,并调用相应回调方法。
协议号的作用就是用来确定用于解析数据的解析类,所以也可以称为协议类型名,可以是string和int类型的数据。
首选我们来定制协议类型:
客户端会用到的协议类: Client.proto
//发送登录请求类
message CSLoginReq
{
required CSLoginInfo LoginInfo = 1;
}
服务端返回用到的协议类:Server.proto
//服务器返回的登录请求回包数据
message CSLoginRes
{
required uint32 result_code = 1;
}
前后端都会用到的协议类:Common.proto
//登陆信息类
message CSLoginInfo
{
required string UserName = 1;//账号
required string Password = 2;//密码
}
然后来定制协议号, 一般放在 Common.proto
//枚举协议号
enum EnmCmdID
{
CS_LOGIN_REQ = 10001;//客户端登陆请求协议号
CS_LOGIN_RES = 10002;//服务器返回的登陆请求的回包协议号
}
以上就是前后端共同定制的消息结构,然后会使用protobuf序列化工具,把protobuf转换成c#类脚本供unity使用。
使用protobuf中的protoc.exe和protogen.exe将这三个protobuf脚本转换成C#类 一般公司都会有专门的工具会批处理这些pb文件的。 然后将生成的.cs代码放到我们的unity工程中。 下面就可以在客户端直接使用这三个类发送消息了
using UnityEngine;
using System.Collections;
using System;
using ProtoBuf;
using System.IO;
public class TestProtobuf : MonoBehaviour {
void Start () {
//构建登陆类
CSLoginInfo mLoginInfo = new CSLoginInfo();
mLoginInfo.UserName = "LYZY";
mLoginInfo.Password = "666666";
CSLoginReq mReq = new CSLoginReq();
mReq.LoginInfo = mLoginInfo;
//下面就是利用通信类的打包方法将这个发送到服务器端就行了
//我们公司直接这样就好了,这里NetworkManager是自己设计封装的一个负责处理网络连接的单例类
NetworkManager.Instance.SendToGameServer(mReq);
//不同的项目发送网络数据的方法不同,一般都是底层构建好的socket TCP/UDP网络通信协议管道
//......
}
}
这样就可以把我们的登陆信息发送到服务器了。
当我们发送消息过去之后,服务器那边会根据消息号来判断,然后给客户端对应的数据处理。这主要是后端做的事情啦!
下面是服务端返回消息后客户端进行监听处理:
//注册监听反信
MessagePublisher.Instance.Subscribe(OnReplyLogin);
//接收到服务器反信后的处理,这里以一个登录成功就领取奖励为例
public void OnReplyLogin(LoginReply reply)
{
if (reply != null)
{
OnLoginRewardReply(reply.claimReward);
}
}
private void OnLoginRewardReply(CliamRewardReply rewardsReply)
{
if (rewardsReply.result == Common.RESULT.RESULT_SUCCESS)
{
LoadClaimReward(rewardsReply);
}
else
{
Debug.Log("领取奖励失败");
}
}
其实说白了,probuf’用于前后端通信的时候就是通过规定的语法内容来进行二进制的一些数据处理,这样比利用json和xml传输效率要高一点,但是公司中既然使用了protobuf这种数据交换格式,肯定会有一套成熟的机制来处理这些文件的,但是一定要明白如何定制消息,发送消息,然后服务器会给我们的是什么样子的内容,搞清楚了这些东西后,管他用什么来传输呢。