谷歌开源项目ProtoBuf再探(与Netty相关)

简介: 谷歌开源项目ProtoBuf再探(与Netty相关)

题为谷歌开源项目ProtoBuf一探(基础环境配置)文章奠定了走进ProtoBuf的世界的路基,环境配置完成后,就正式地开启旅程。


第一站:ProtoBuf语义


既然是一门新的编程语言(使命是定义数据结构),我们就需要去掌握其中语义。学习其它任何语言都一样。语法规则搞懂了,剩下的就是逻辑码代码。以下面代码为例,附带注释。


syntax = "proto2";//定义协议版本,现在出来了proto3
package tutorial;//定义该文件的包名
option java_package = "com.example.tutorial";//定义输出java文件的包名
option java_outer_classname = "AddressBookProtos";//定义输出java文件的类名
message Person { //定义消息数据结构名称
  required string name = 1;//字段修饰
  required int32 id = 2;
  optional string email = 3;
  enum PhoneType {//定义枚举类型
    MOBILE = 0;
    HOME = 1;
    WORK = 2;
  }
  message PhoneNumber {
    required string number = 1;
    optional PhoneType type = 2 [default = HOME];//默认值为HOME=1
  }
  repeated PhoneNumber phones = 4;
}
message AddressBook {
  repeated Person people = 1;
}

从上述代码中可以看出,Person消息数据结构包含若干基本类型,如boolint32string,enum等。数据类型前有且仅有这三种修饰符。如下表所示。


修饰符 含义
required 字段属性为必须,否则消息被视为未初始化
optional 字段属性为可选,若该字段未被初始,就会持有其设置的默认值;也可以不设置,系统会设置默认值
repeated 字段属性为重复,重复的字段在Protocol Buffer中保存

在代码中,也能看到可以嵌套消息数据结构。这在输出的Java文件得出对应的嵌套静态常量类。这样就极大地丰富了自定义协议的灵活性。可以任意组合出N种类型的消息数据结构。

Protocol Buffer系统默认值如下表所示:

数据类型 默认值
int32 0
string 空字符串
enum 第一个值
bool false


如果枚举类型中,枚举类型的必须是32bit 的整数值;想让其中两个值相等,必须开启别号功能即option allow_alias = true,如下代码所述。


enum EnumAllowingAlias {
  option allow_alias = true;
  UNKNOWN = 0;
  STARTED = 1;
  RUNNING = 1;
}
enum EnumNotAllowingAlias {
  UNKNOWN = 0;
  STARTED = 1;
  // RUNNING = 1;  // Uncommenting this line will cause a compile error inside Google and a warning message outside.
}

其它需要注意的地方请参照官方指导1


第二站:入驻Netty城


Netty作为一种高扩展-异步-事件驱动型通信框架已经享誉国内外。在该框架中,拥有市场上存在的很多协议的编解码器,如HTTP,WebSocket,MQTT,SMTP,SSL等。这极大地缩短了开发者的研发周期。避免重复造轮子。

在写好ChannelInboundHandler或者ChannelOutboundHandler处理器后,就需要进行测试,或许你会采用开启客户端和服务端来看是否工作正常,这样显得太笨重了。而且有小问题也不容易查看出。这时一个嵌入的通道在Netty中应运而生,它就是EnbededChannel,它的两对方法极为重要。其余方法请看官方API2。如下表所示。


方法 作用
public boolean writeOutbound(Object… msgs) 向通道中写出站数据
public T readOutbound() 从通道中读经过出站处理器处理后的数据(如编码)
public boolean writeInbound(Object… msgs) 向通道中写出入站数据
public T readInbound() 从通道中读经过入站处理器处理后的数据(如解码)


当自定义好ProtoBuf协议后,编译出java文件,导入项目工程中。然后利用Netty自带的编解码器进行测试。代码如下。


@Test
    public void testAlarmProto(){
      //构建消息类型
        MessageProto.MessageBase.Header.Builder header =MessageProto.MessageBase.Header.newBuilder();
        header.setType(MessageProto.MessageBase.MessageType.SERVICE_REQ);
        MessageProto.MessageBase.Builder message = MessageProto.MessageBase.newBuilder();
        message.setHeader(header.build());
        //构建带有处理器的通道
        EmbeddedChannel ch = new EmbeddedChannel();
        ch.pipeline().addLast("frameDecoder",new ProtobufVarint32FrameDecoder());
        ch.pipeline().addLast("decoder",new ProtobufDecoder(MessageProto.MessageBase.getDefaultInstance()));
        ch.pipeline().addLast("frameEncoder",new ProtobufVarint32LengthFieldPrepender());
        ch.pipeline().addLast("encoder",new ProtobufEncoder());
        /**
         * TODO:先写入数据进行编码,然后再读出数据进行解码
         */
        ch.writeOutbound(message.build());
        ByteBuf byteBuf = ch.readOutbound();
        System.out.println(byteBuf.toString());
        ch.writeInbound(byteBuf);
        ch.finish();
        MessageProto.MessageBase messageBase = ch.readInbound();
        System.out.println(messageBase.getHeader().getType().getNumber());
        System.out.println(messageBase.getBody().getContext().getBuildingPart());
    }

能够从POJO到POJO就表示成功 ? 。


https://developers.google.com/protocol-buffers/docs/proto ↩︎


https://netty.io/4.1/api/index.html ↩︎


相关文章
|
SQL 关系型数据库 Linux
在CentOS 6上安装和使用PostgreSQL的方法
在CentOS 6上安装和使用PostgreSQL的方法
296 2
|
测试技术 API 数据安全/隐私保护
Python连接到Jira实例、登录、查询、修改和创建bug
通过使用Python和Jira的REST API,可以方便地连接到Jira实例并进行各种操作,包括查询、修改和创建Bug。`jira`库提供了简洁的接口,使得这些操作变得简单易行。无论是自动化测试还是开发工作流的集成,这些方法都可以极大地提高效率和准确性。希望通过本文的介绍,您能够更好地理解和应用这些技术。
1277 0
大文件上传如何断点续传
该文档描述了一个大文件上传流程,包括:1) 文件分片,2) 计算文件及分片的Hash值以生成唯一标识符,3) 上传分片并检查已上传状态以避免重复,4) 在上传中断时能恢复,5) 服务端合并分片成原始文件,6) 错误处理(如网络中断、服务器故障、上传失败等)并通知用户,最后7) 返回上传成功信息。
300 0
|
SQL Go 索引
SQL Server 临时表和表变量系列之认知误区篇
# 摘要 关于临时表和表变量,是一个老生常谈的话题,但是,我相信很多SQL Server老司机都存在或多或少的认知误区。指出一些常见的认知误区就是写作本文的目的,希望以此来找到一些常常被我们忽略的地方。 # 认知误区 SQL Server关于临时表和表变量的常见的认知误区包含以下六点: 表变量不支持事务 表变量不能创建索引 表变量没有统计信息 表变量存驻留在内存中 表变量
6166 0
|
关系型数据库 MySQL 数据安全/隐私保护
|
2天前
|
存储 JavaScript 前端开发
JavaScript基础
本节讲解JavaScript基础核心知识:涵盖值类型与引用类型区别、typeof检测类型及局限性、===与==差异及应用场景、内置函数与对象、原型链五规则、属性查找机制、instanceof原理,以及this指向和箭头函数中this的绑定时机。重点突出类型判断、原型继承与this机制,助力深入理解JS面向对象机制。(238字)
|
1天前
|
云安全 人工智能 安全
阿里云2026云上安全健康体检正式开启
新年启程,来为云上环境做一次“深度体检”
1467 6
|
3天前
|
安全 数据可视化 网络安全
安全无小事|阿里云先知众测,为企业筑牢防线
专为企业打造的漏洞信息收集平台
1303 2
|
3天前
|
缓存 算法 关系型数据库
深入浅出分布式 ID 生成方案:从原理到业界主流实现
本文深入探讨分布式ID的生成原理与主流解决方案,解析百度UidGenerator、滴滴TinyID及美团Leaf的核心设计,涵盖Snowflake算法、号段模式与双Buffer优化,助你掌握高并发下全局唯一ID的实现精髓。
319 160

热门文章

最新文章