更小、更快、更简单 Google ProtoBuf 跨语言通信协议

栏目: 服务器 · 发布时间: 7年前

内容简介:更小、更快、更简单 Google ProtoBuf 跨语言通信协议

背景:

这几天在写一个服务端的socket的通讯服务器,之前是自己定义的协议因为,因为只是android客户端和服务器通讯,后来iOS也连接到这个socket服务器上,为了跨语言通讯,发现Google的 ProtoBuf(Protocol Buffer)支持跨语言通讯,而且效率非常高。

ProtoBuf是什么?

Google Protocol Buffer( 简称 Protobuf) 是 Google 公司内部的混合语言数据标准,后来才开源的,它是一个灵活、高效、结构化的序列化数据结构,它与传统的XML等通讯相比,它的更小、更快、更简单。

protoBuf的优点

1.protoBuf在Google内部长期使用,产品稳定成熟,很多商业的项目都选择使用

2.跨语言,它支持 Java 、C++、 Python 、ObJect-c、C#、 Go 等语言,

3.protoBuf编码后消息更小、有利于存储传输

4.编码和解码的效率非常之高

5.支持不同版本的协议向前兼容

6.支持自定义可选和必选字段

更小、更快、更简单 Google ProtoBuf 跨语言通信协议
图片来自网络
更小、更快、更简单 Google ProtoBuf 跨语言通信协议
图片来自网络

protoBuf环境搭建(基于Windows)

我们先要下载ProtoBuf,,下载地址为 https://github.com/google/protobuf/releases?after=v2.6.1

这里我是使用Windows版

更小、更快、更简单 Google ProtoBuf 跨语言通信协议

下载完之后我们解压

更小、更快、更简单 Google ProtoBuf 跨语言通信协议

我们要是的是protoc.exe工具,它是根据.proto文件生成对应的代码转换工具,就这么简单ProtoBuf的编译环境我们已经搞定了。

protoBuf的Demo

这里使用Java语言实现,我们首选要定义一个protoBuf格式的通讯协议,Login.proto文件

package test;
option java_package = "sg.com.protobuf";
option java_outer_classname = "LoginProto";
message Login{
  required int32 id = 1;
  required string name = 2;
  required string pws = 3;
  optional string email = 4;
}

package:指定生成Java代码文件的包名

java_package:指定生Java类的包名

java_outer_classname:指定生成Java代码的外部类名称。如果没有指定该选项,Java代码的外部类名称为当前文件的文件名部分,同时还要将文件名转换为驼峰格式,如:my_project.proto

message:protoBuf消息定义的关键字,相当于Java中的class

required:数据类型的前缀,表示该字段为必要字段,既在序列化和反序列化之前该字段必须已经被赋值

repeated:表示这个字段的值可以允许被重复多次,如果转换成JAVA代码,此filed数据结构为list,有序的。可以在“repeated”类型的filed后使用“packed”--压缩,提高数据传输的效率。

optional: 表示这个值是可选的允许为null

ProtoBuf类型和Java类型对应关系

更小、更快、更简单 Google ProtoBuf 跨语言通信协议

ProtoBuf支持枚举类型,protobuf中enum类型的每个值是一个int32的数字,不像JAVA中那样enum可以定义的非常复杂。如果enum中有些值是相同的,可以将“allow_alias”设定为true

完成消息的定义之后,就可以通过protoc.exe编译了

更小、更快、更简单 Google ProtoBuf 跨语言通信协议

编译的命令格式

protoc.exe -I=proto的输入目录 --java_out=java类输出目录 proto的输入目录包括包括proto文件.

编译好java类后,我们就可以实例化和序列化了

LoginProto.Login.Builder builder = LoginProto.Login.newBuilder();
        builder.setId(1);
        builder.setName("sgtest");
        builder.setPws("123");
        builder.setEmail("test@163.com");
        //获取login的实例
        LoginProto.Login login = builder.build();
        System.out.println(login);
        //序列化
        System.out.println("---------");
        byte[] bytes = login.toByteArray();
        System.out.println("leng:"+bytes.length);
        login =LoginProto.Login.parseFrom(bytes);
        System.out.println(login);

实例化一个对象是非常方便的,使用Google给我们生成的静态方法就可以,通过toByteArray()方法来实现序列,parseFrom(bytes)方法来实现反序列化,你会看到protoBuf序列化后的字节长度非常小,这个还不算强大的,下面再来看一中序列化的方式:

//第二种序列化
        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
        login.writeDelimitedTo(byteArrayOutputStream);
      //反序列化
        ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(byteArrayOutputStream.toByteArray());
        login = LoginProto.Login.parseDelimitedFrom(byteArrayInputStream);
        System.out.println(login.getEmail());

做过大量socket数据传输的同学都知道,socket很容易发生粘包、拆包的问题,会导致数据解析错误,protoBuf可以搞定它,login.writeDelimitedTo(byteArrayOutputStream)方法,将一个对象序列化输出到一个字节数组流中,它在序列化的字节数组之前,添加一个varint32的数字表示字节数组的长度,所以实际放在字节数据中内容应该是数据的长度加上数据的内容,下面是该方法的源码

更小、更快、更简单 Google ProtoBuf 跨语言通信协议

在解码通过先读取varint,再读取此长度的字节;这种方式有效的解决了socket传输时粘包、拆包的问题。

最后给出demo下载地址: http://download.csdn.net/detail/mtx_20103276/9867367

以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

组成论

组成论

张学文 / 中国科学技术大学出版社 / 2003-12 / 35.00元

很多事物中都存在组成(成分、构成)问题。作者创立的组成论为此提供统一的认识模型、分析工具、计算方法和原理。它通过广义集合、分布函数和复杂程度三个概念分析事物组成,并揭示了有随机性的事物都遵守最复杂原理。组成论与系统科学、复杂性研究、信息论和热力学第二定律关系密切。本书介绍了它在自然和社会科学中的许多应用,还提出了信息不可增殖、不同形态的复杂程度的互相转化(复杂度定律)等重要论点。自然科学、社会科学......一起来看看 《组成论》 这本书的介绍吧!

随机密码生成器
随机密码生成器

多种字符组合密码

Base64 编码/解码
Base64 编码/解码

Base64 编码/解码

HEX HSV 转换工具
HEX HSV 转换工具

HEX HSV 互换工具