1.Win版Protobuf代码生成工具下载:

https://github.com/protocolbuffers/protobuf/releases

注意下载protoc-3.6.1-win32.zip

2.编写.proto文件注意:

指定包为外层目录名称,指定java包名为你想使用的java工程该序列化类包名,还需要指定生成Java类的名称。字段赋予的数值或代表次序,而不是字段默认值。示例:

syntax = "proto2";
package Protobuf;
option java_package = "com.xiaobai.codec.protobuf";
option java_outer_classname = "SubscribeReqProto"; message SubscribeReq{
required int32 subReqID = 1;
required string userName = 2;
required string productName = 3;
repeated string address = 4;
}
syntax = "proto2";
package Protobuf;
option java_package = "com.xiaobai.codec.protobuf";
option java_outer_classname = "SubscribeRespProto"; message SubscribeResp{
required int32 subReqID = 1;
required int32 respCode = 2;
required string desc = 3;
}

3.使用工具时需要注意

a.需要指定一个--proto_path路径,根据错误提示:

D:\protoc-3.6.1-win32\bin>protoc.exe --java_out=F:\NewAge\nettydemo\src\main\jav
a F:\NewAge\nettydemo\Protobuf\SubscribeReq.proto
F:\NewAge\nettydemo\Protobuf\SubscribeReq.proto: File does not reside within any
path specified using --proto_path (or -I). You must specify a --proto_path whi
ch encompasses this file. Note that the proto_path must be an exact prefix of t
he .proto file names -- protoc is too dumb to figure out when two paths (e.g. ab
solute and relative) are equivalent (it's harder than you think).

这个路径需要是.proto文件所在目录

b.需要在.proto文件中指定它的proto语法版本,这样生成时不会出现警告,根据提示,这个版本默认是proto2,可以设置为proto3:

D:\protoc-3.6.1-win32\bin>protoc.exe --proto_path=F:\NewAge\nettydemo\Protobuf -
-java_out=F:\NewAge\nettydemo\src\main\java F:\NewAge\nettydemo\Protobuf\Subscri
beReq.proto
[libprotobuf WARNING T:\src\github\protobuf\src\google\protobuf\compiler\parser.
cc:562] No syntax specified for the proto file: SubscribeReq.proto. Please use '
syntax = "proto2";' or 'syntax = "proto3";' to specify a syntax version. (Defaul
ted to proto2 syntax.)

参照:

https://www.jianshu.com/p/42a480a45cd6

https://www.cnblogs.com/gifisan/p/5976208.html?utm_source=itdadao&utm_medium=referral

生成效果如下:

Win版本安装参考与示例:

https://www.cnblogs.com/tyw66/p/7352033.html

Linux版本安装参考与示例:

https://www.cnblogs.com/learn21cn/p/6206206.html

https://www.cnblogs.com/luoxn28/p/5303517.html

4.实践时采用了3.6.1版本代码生成,所以Java工程引入依赖也选择了3.6.1版本,且重新用proto3生成了代码,该语法不支持required字段,所以去掉:

D:\protoc-3.6.1-win32\bin>protoc.exe --proto_path=F:\NewAge\nettydemo\Protobuf -
-java_out=F:\NewAge\nettydemo\src\main\java F:\NewAge\nettydemo\Protobuf\Subscri
beResp.proto
SubscribeResp.proto: Required fields are not allowed in proto3.
SubscribeResp.proto: Required fields are not allowed in proto3.
SubscribeResp.proto: Required fields are not allowed in proto3.

syntax = "proto3";
package Protobuf;
option java_package = "com.xiaobai.codec.protobuf";
option java_outer_classname = "SubscribeReqProto"; message SubscribeReq{
int32 subReqID = 1;
string userName = 2;
string productName = 3;
repeated string address = 4;
}
syntax = "proto3";
package Protobuf;
option java_package = "com.xiaobai.codec.protobuf";
option java_outer_classname = "SubscribeRespProto"; message SubscribeResp{
int32 subReqID = 1;
int32 respCode = 2;
string desc = 3;
}

注意Protobuf里面没有list,需要指定为repeated + 元素类型!!

未写元素类型导致的报错:

D:\protoc-3.6.1-win32\bin>protoc.exe --proto_path=F:\NewAge\nettydemo\Protobuf -
-java_out=F:\NewAge\nettydemo\src\main\java F:\NewAge\nettydemo\Protobuf\Subscri
beReq.proto
SubscribeReq.proto:10:22: Expected field name.

参照(定义复杂对象):

https://blog.csdn.net/hry2015/article/details/70766603

https://blog.csdn.net/qq_33951440/article/details/80599712

5.源码中的报错:@Override问题和支持1.6+的Java版本问题

参考https://blog.csdn.net/jdjdndhj/article/details/70256789

是因为IDEA源码版本设置的原因:

6.编译报错

Error:java: Compilation failed: internal java compiler error

这是IDEA编译版本设置的原因,注意本项目(nettydemo)的编译版本也要设置成1.8,这里是坑:

参考:https://www.cnblogs.com/comeluder/p/8215317.html

7.序列化测试

package com.xiaobai.codec.protobuf;

import com.google.protobuf.InvalidProtocolBufferException;

import java.util.ArrayList;
import java.util.List; public class TestSubscribeReqProto { private static byte[] encode(SubscribeReqProto.SubscribeReq req) {
return req.toByteArray();
} private static SubscribeReqProto.SubscribeReq decode(byte[] body) throws InvalidProtocolBufferException {
return SubscribeReqProto.SubscribeReq.parseFrom(body);
} private static SubscribeReqProto.SubscribeReq createSubScribeReq() {
SubscribeReqProto.SubscribeReq.Builder builder = SubscribeReqProto.SubscribeReq.newBuilder();
builder.setSubReqID(1);
builder.setUserName("xiaobai");
builder.setProductName("Java Supior");
List<String> address = new ArrayList<>();
address.add("Shenyang YUEXING");
address.add("Jinzhou HUAGUANG");
address.add("Beijing HAIDIAN");
builder.addAllAddress(address);
return builder.build();
} public static void main(String[] args) throws InvalidProtocolBufferException {
SubscribeReqProto.SubscribeReq req = createSubScribeReq();
System.out.println("Before encoding: ");
System.out.println(req.toString());
SubscribeReqProto.SubscribeReq req2 = decode(encode(req));
System.out.println("After encoding and decoding: ");
System.out.println(req2.toString());
System.out.println("Assert enqual: --> " + req2.equals(req));
}
}

输出结果:

Before encoding:
subReqID: 1
userName: "xiaobai"
productName: "Java Supior"
address: "Shenyang YUEXING"
address: "Jinzhou HUAGUANG"
address: "Beijing HAIDIAN"

After encoding and decoding:
subReqID: 1
userName: "xiaobai"
productName: "Java Supior"
address: "Shenyang YUEXING"
address: "Jinzhou HUAGUANG"
address: "Beijing HAIDIAN"

Assert enqual: --> true

8.结合netty(netty版本需要5.0.0.Alpha1

ChannelHandlerAdapter版本问题:

https://my.oschina.net/linwl/blog/1823315

ChannelHandlerAdapter分析:

https://www.cnblogs.com/wade-luffy/p/6222960.html

GitHub:https://github.com/Xiaobai0419/nettydemo

注意:

a.例子中客户端和服务端可一直保持连接,和双向互传数据。如果一方断开,另一方报异常:

java.io.IOException: 远程主机强迫关闭了一个现有的连接。
at sun.nio.ch.SocketDispatcher.read0(Native Method)
at sun.nio.ch.SocketDispatcher.read(SocketDispatcher.java:43)
at sun.nio.ch.IOUtil.readIntoNativeBuffer(IOUtil.java:223)
at sun.nio.ch.IOUtil.read(IOUtil.java:192)
at sun.nio.ch.SocketChannelImpl.read(SocketChannelImpl.java:380)
at io.netty.buffer.UnpooledUnsafeDirectByteBuf.setBytes(UnpooledUnsafeDirectByteBuf.java:446)
at io.netty.buffer.AbstractByteBuf.writeBytes(AbstractByteBuf.java:871)
at io.netty.channel.socket.nio.NioSocketChannel.doReadBytes(NioSocketChannel.java:208)
at io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:119)
at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:485)
at io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:452)
at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:346)
at io.netty.util.concurrent.SingleThreadEventExecutor$5.run(SingleThreadEventExecutor.java:794)
at java.lang.Thread.run(Thread.java:748)

需要进行处理。

客户端重新连接,仍可与服务端继续通信。

b.例子中序列化类int类型字段值为0无法传输该字段,其他值则可以,待查。

Google Protobuf结合Netty实践的更多相关文章

  1. 《精通并发与Netty》学习笔记(05 - Google Protobuf与Netty的结合)

    protobuf是由Google开发的一套对数据结构进行序列化的方法,可用做通信协议,数据存储格式,等等.其特点是不限语言.不限平台.扩展性强 Netty也提供了对Protobuf的天然支持,我们今天 ...

  2. 《精通并发与Netty》学习笔记(04 - Google Protobuf介绍)

    一 .Google Protobuf 介绍 protobuf是google团队开发的用于高效存储和读取结构化数据的工具,是Google的编解码技术,在业界十分流行,通过代码生成工具可以生成不同语言版本 ...

  3. netty 的 Google protobuf 开发

    根据上一篇博文 Google Protobuf 使用 Java 版 netty 集成 protobuf 的方法非常简单.代码如下: server package protobuf.server.imp ...

  4. Netty学习——Google Protobuf使用方式分析和环境搭建

    Google Protobuf使用方式分析 在RPC框架中,Google Protobuf是很常用的一个库,和Apache Thrift 是同款的用于进行序列化的第三方库.原理都是大同小异,无非就是使 ...

  5. google protobuf 简单实例

    1.定义proto文件: User.proto package netty; option java_package="myprotobuf"; option java_outer ...

  6. (中级篇 NettyNIO编解码开发)第八章-Google Protobuf 编解码-2

    8.1.2    Protobuf编解码开发 Protobuf的类库使用比较简单,下面我们就通过对SubscrjbeReqProto进行编解码来介绍Protobuf的使用. 8-1    Protob ...

  7. (中级篇 NettyNIO编解码开发)第八章-Google Protobuf 编解码-1

    Google的Protobuf在业界非常流行,很多商业项目选择Protobuf作为编解码框架,这里一起回顾一下Protobuf    的优点.(1)在谷歌内部长期使用,产品成熟度高:(2)跨语言,支持 ...

  8. Google Protobuf 使用 Java 版

    一 . Protobuf 的入门 Protobuf 是一个灵活,高效,结构化的数据序列化框架, 相比于 XML 等传统的序列化工具,它更小,更快,更灵活,更简单. Protobuf 支持数据结构化一次 ...

  9. 京东的Netty实践,京麦TCP网关长连接容器架构

    背景 早期京麦搭建 HTTP 和 TCP 长连接功能主要用于消息通知的推送,并未应用于 API 网关.随着逐步对 NIO 的深入学习和对 Netty 框架的了解,以及对系统通信稳定能力越来越高的要求, ...

随机推荐

  1. Python全栈-网络编程-TCP粘包

    一.什么是TCP粘包 C/S架构下,接收方不知道每个消息的发送间隙.也不知道每次应该提取多少个字节的数据,与此同时,TCP是面向连接的,面向流的,收发两端都要有,因此发送端为了将多个发往接收端的数据包 ...

  2. vs远程调试 转http://www.cnblogs.com/magicchaiy/archive/2013/05/28/3088274.html

    远程调试应用场景 部署环境:ASP.NET(C#)+IIS+Win7 64 bit 很多公司的开发模式都是将开发机器和服务器分开,也就是开发一台机,服务器一台机.而测试人员会在服务器上录入测试数据,此 ...

  3. UML之状态机图

    状态机图 基本概念: 状态机图,UML 1.x规范中称状态图,是一个展示状态机的图. 状态机图基本上就是一个状态机中元素的投影,这也就意味着状态机图包括状态机的所有特征.状态机图显示了一个对象如何根据 ...

  4. hdu5290树形dp

    题意 给了n个点的数 每个点有一个w[i]权值,如果你选择了i这个点那么距离i这个点距离为w[i]的点将被除去,最后问 选则尽量少的点把这n个点全部删除 1<=n<=100000, 0&l ...

  5. 网关绑定命令,解决arp攻击

    一般家里的宽带都采用ADSL设备,通过固定IP地址接入Internet,但是经常会出现断网的现象,那么如何通过ARP命令绑定默认网关来解决这个问题呢? 工具/原料 ARP命令 CMD命令提示符 方法/ ...

  6. mybatis源码解析2---SqlSessionFactoryBuilder、SqlSessionFactory解析

    1.先看一个mybatis最简单的Demo String resource = "mybatis-config.xml"; //1.流形式读取mybatis配置文件 InputSt ...

  7. Linux基础命令---tracepath追踪路由信息

    tracepath tracepath指令可以追踪数据到达目标主机的路由信息,同时还能够发现MTU值.它跟踪路径到目的地,沿着这条路径发现MTU.它使用UDP端口或一些随机端口.它类似于Tracero ...

  8. LINUX安装REDIS集群

    linux安装单机版redis已经在另一篇文章说过了,下边来搞集群,环境是新浪云服务器: redis3.0以后开始支持集群. 前言:redis用什么做集群? 用一个叫redis-trib.rb的rub ...

  9. 几张图看明白VAO、VBO、EBO的关系和代码顺序

    0.详细教程可看https://learnopengl-cn.github.io/01%20Getting%20started/04%20Hello%20Triangle/ 1.可以简单地认为VAO的 ...

  10. ubuntu 18.04下安装配置Hue问题记录

    前段时间将Hadoop 在ubuntu环境下装好,接下来尝试安装Hue来管理Hadoop,参照的资料有: 1.高可用Hadoop平台-Hue In Hadoop 2.ubuntu16.04 安装单机H ...