首页 > 其他分享 >网络通信 数据交互结构 Protobuffer

网络通信 数据交互结构 Protobuffer

时间:2022-11-17 18:59:32浏览次数:68  
标签:网络通信 解析 string Protobuffer Json 消息 序列化 交互

消息头:消息唯一标识,用来区分当前网络请求的类型。登陆就做账号验证,聊天就做消息群发。

一般使用数字表示,字符串比较耗内存。1byte范围为0 ~ 255,2byte范围为0 ~ 65535,消息头一般情况2byte就够了。

消息体:真正传输的数据。

假设1001为登陆请求,1004为聊天功能。

// 假设是收到的消息
byte[] 接收到的消息 = null;
// 创建数组存储消息头数据
byte[] header = new byte[2];
// 给存储消息头的数组赋值
header[0] = 接收到的消息[0];
header[1] = 接收到的消息[1];
// 将存储消息头的数组转换成int类型
int messgeld = BitConverter.ToInt32(header, 0);
// 消息体数据
byte[] body = new byte[接收到的消息.Length - 2];
for (int i = 0; i < 接收到的消息.Length - 2; i++) {
    body[i] = 接收到的消息[i + 2];
}

if (messgeld == 1001) {
    // 执行登录数据逻辑
} else if (messgeld == 1004) {
    // 执行聊天功能
}

服务器和客户端都可以使用Json将复杂的数据序列化成字节数组进行传递。

但服务器和客户端都需要写对应的解析类(客户端一份,服务器一份,且两者的解析类必须一样)。

Protobuffer

用途:和Json相似,功能无非是序列化和反序列化。

在序列化和反序列化上有建立一个体系,使用协议文件生成对应平台的代码。协议文件写完使用软件生成对应平台的解析类。

两者比较:

  • 效率高,序列化/反序列化比Json还要快(快20~100倍),产生的字节流比Json还要小(数据可缩小3倍)。做网络传输比Json更省性能。
  • 跨语言。
  • 提供了程序,方便从Proto文件直接生成编程中可实际使用的类文件。
  • 可自动生成序列化和反序列化的接口。
  • Protobuffer不可读,Json可读。

Protobuffer 字段规则

字段规则 说明
required 字段必须出现且仅能出现一次
optional 字段可出现0次或1次
repeated 字段可出现任意次(包括0次)相当于动态数组

在每个message中至少要有一个required类型的字段。

// 类
message Invite {
    // 必填,后面为编号
    required string host = 1;
    required string name = 2;
    required string address = 3;
    // 选填
    optional string info = 4;
}

protobuffer 中的枚举和C#中的一样,类型也是可以嵌套的。

Protobuffer 具体使用

生成解析类工具、pb.dll、ProtoBufUtil.cs

  1. 先创建一个ProtoTest.proto结尾的文件,建议使用VsCode下载一个protobuf插件即可。

  2. 前后端根据需求制定协议。

    // 登录
    message LoginReq { 
        required string account = 1;
        repeated string password = 2;
    }
    
  3. 将刚定义好的协议文件使用软件生成指定的解析类(将.proto文件放置到Tools\ProtoGenTool\proto下,运行_生成Protocol - 批量生成的解析类在Tools\ProtoGenTool\cs下)。

  4. 将生成的解析类拖入项目。

  5. 将Protobuffer解析库拖入项目(pb.dll、ProtoBufUtil.cs)。

  6. Protobuffer序列化反序列化测试。

    using UnityEngine;
    // 生成的解析类
    using proto.ProtoTest;
    
    public class Test : MonoBehaviour {
        void Start() {
            LoginReq login = new LoginReq();
            login.account = "SSSS";
            login.password = "vv";
            // 把对象序列化字节数据
            byte[] data = ProtoBufUtils.Serialize(login);
    
            var obj = ProtoBufUtils.Deserialize<LoginReq>(data);
            Debug.LogFormat("账号:{0},密码:{1}", obj.account, obj.password);
        }
    }
    

标签:网络通信,解析,string,Protobuffer,Json,消息,序列化,交互
From: https://www.cnblogs.com/wuzhongke/p/16900445.html

相关文章