更小、更快、更简单 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

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

查看所有标签

猜你喜欢:

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

Introduction to Linear Optimization

Introduction to Linear Optimization

Dimitris Bertsimas、John N. Tsitsiklis / Athena Scientific / 1997-02-01 / USD 89.00

"The true merit of this book, however, lies in its pedagogical qualities which are so impressive..." "Throughout the book, the authors make serious efforts to give geometric and intuitive explanations......一起来看看 《Introduction to Linear Optimization》 这本书的介绍吧!

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

多种字符组合密码

UNIX 时间戳转换
UNIX 时间戳转换

UNIX 时间戳转换

RGB CMYK 转换工具
RGB CMYK 转换工具

RGB CMYK 互转工具