Google Protobuf是一种轻便高效的结构化数据存储格式,可以用于结构化数据序列化。它很适合做数据存储或 RPC 数据交换格式。可用于通讯协议、数据存储等领域的语言无关、平台无关、可扩展的序列化结构数据格式。

编译安装:

下载Java版 https://github.com/google/protobuf/releases

tar -zxvf xxx.tar.gz

./configure

make

make install

protoc --version

mvn install

mvn package

使用:

Google Protobuf支持复杂的POJO对象的编解码,而这些代码是自动生成的。

首先写文件Person.proto ,定义程序中需要处理的结构化数据,在 protobuf 的中,结构化数据被称为 Message。

syntax="proto3";
package com.luangeng.netty.protobuf; message Person {
string username=1; //
int32 age=2; //
string sex=3; //
}

执行命令

protoc -I=. --java_out=. Person.proto

格式: protoc -I=$SRC_DIR --cpp_out=$DST_DIR $SRC_DIR/***.proto

即在当前目录下生成了Java文件PersonOutClass.java, 将它引入到工程并需要添加POM依赖

<dependency>
<groupId>com.google.protobuf</groupId>
<artifactId>protobuf-java</artifactId>
<version>3.5.0</version>
</dependency>

--

然后做一个简单的编解码测试:

public class TestProtoBuf {

    //编码为byte数组
private static byte[] encoder(PersonOuterClass.Person p) {
return p.toByteArray();
} //从byte数组解码
private static PersonOuterClass.Person decoder(byte[] b) throws InvalidProtocolBufferException {
return PersonOuterClass.Person.parseFrom(b);
} //使用builder实例来设置属性
private static PersonOuterClass.Person create(){
PersonOuterClass.Person.Builder builder = PersonOuterClass.Person.newBuilder();
builder.setAge(10);
builder.setSex("man");
builder.setUsername("luangeng");
return builder.build();
} public static void main(String[] args) throws InvalidProtocolBufferException {
PersonOuterClass.Person p = create();
Q.p("before----------\n" + p.toString()); PersonOuterClass.Person p2 = decoder(encoder(p));
Q.p("afetr-----------\n" + p2.toString());
} }

---

输出结果:

before----------
username: "luangeng"
age: 10
sex: "man"

afetr-----------
username: "luangeng"
age: 10
sex: "man"

在Netty中使用Google Protobuf实例:

Server端:

public class EchoServer {
public static void main(String[] args) {
new EchoServer().bind(8080);
} public void bind(int port) {
EventLoopGroup bossGroup = new NioEventLoopGroup();
EventLoopGroup workerGroup = new NioEventLoopGroup();
try {
ServerBootstrap bootstrap = new ServerBootstrap();
bootstrap.group(bossGroup, workerGroup)
.channel(NioServerSocketChannel.class)
.option(ChannelOption.SO_BACKLOG, 100)
.childHandler(new ChannelInitializer<SocketChannel>() {
@Override
protected void initChannel(SocketChannel ch) throws Exception {
ch.pipeline().addLast(new ProtobufVarint32FrameDecoder());
ch.pipeline().addLast(new ProtobufDecoder(PersonOuterClass.Person.getDefaultInstance()));
ch.pipeline().addLast(new ProtobufVarint32LengthFieldPrepender());
ch.pipeline().addLast(new ProtobufEncoder());
ch.pipeline().addLast(new EchoServerHandler());
}
});
ChannelFuture future = bootstrap.bind(port).sync();
System.out.println("server started");
future.channel().closeFuture().sync();
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
System.out.println("server shuting down");
bossGroup.shutdownGracefully();
workerGroup.shutdownGracefully();
}
}
} public class EchoServerHandler extends ChannelInboundHandlerAdapter {
int count = 0; @Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
PersonOuterClass.Person p = (PersonOuterClass.Person) msg;
System.out.println("Server received " + count++ + " :\n" + p.toString());
ctx.writeAndFlush(msg);
} @Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
cause.printStackTrace();
ctx.close();
}
}

---

Client端:

public class EchoClient {

    public static void main(String[] args) {
new EchoClient().connect("127.0.0.1", 8080);
} public void connect(String host, int port) {
EventLoopGroup group = new NioEventLoopGroup();
try {
Bootstrap bootstrap = new Bootstrap();
bootstrap.group(group).channel(NioSocketChannel.class)
.option(ChannelOption.TCP_NODELAY, true)
.handler(new ChannelInitializer<SocketChannel>() {
protected void initChannel(SocketChannel ch) throws Exception {
ch.pipeline().addLast(new ProtobufVarint32FrameDecoder());
ch.pipeline().addLast(new ProtobufDecoder(PersonOuterClass.Person.getDefaultInstance()));
ch.pipeline().addLast(new ProtobufVarint32LengthFieldPrepender());
ch.pipeline().addLast(new ProtobufEncoder());
ch.pipeline().addLast(new EchoClientHandler());
}
});
ChannelFuture future = bootstrap.connect(host, port).sync();
System.out.println("client started");
future.channel().closeFuture().sync();
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
System.out.println("client shuting down");
group.shutdownGracefully();
}
}
} public class EchoClientHandler extends ChannelInboundHandlerAdapter { private int count = 0; private static PersonOuterClass.Person create(int i) {
PersonOuterClass.Person.Builder builder = PersonOuterClass.Person.newBuilder();
builder.setAge(i);
builder.setSex("man");
builder.setUsername("luangeng" + i);
return builder.build();
} @Override
public void channelActive(ChannelHandlerContext ctx) throws Exception {
for (int i = 0; i < 20; i++) {
ctx.writeAndFlush(create(i));
}
} //服务端返回应答信息后调用
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
PersonOuterClass.Person p = (PersonOuterClass.Person) msg;
Q.p("Client get " + count++ + " :\n" + p.toString());
} @Override
public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
ctx.flush();
} @Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
cause.printStackTrace();
ctx.close();
}
}

---

执行结果:

client started
Client get 0 :
username: "luangeng0"
sex: "man"

Client get 1 :
username: "luangeng1"
age: 1
sex: "man"

Client get 2 :
username: "luangeng2"
age: 2
sex: "man"

Client get 3 :
username: "luangeng3"
age: 3
sex: "man"

Client get 4 :
username: "luangeng4"
age: 4
sex: "man"

Client get 5 :
username: "luangeng5"
age: 5
sex: "man"

Client get 6 :
username: "luangeng6"
age: 6
sex: "man"

Client get 7 :
username: "luangeng7"
age: 7
sex: "man"

Client get 8 :
username: "luangeng8"
age: 8
sex: "man"

Client get 9 :
username: "luangeng9"
age: 9
sex: "man"

Client get 10 :
username: "luangeng10"
age: 10
sex: "man"

Client get 11 :
username: "luangeng11"
age: 11
sex: "man"

Client get 12 :
username: "luangeng12"
age: 12
sex: "man"

Client get 13 :
username: "luangeng13"
age: 13
sex: "man"

Client get 14 :
username: "luangeng14"
age: 14
sex: "man"

Client get 15 :
username: "luangeng15"
age: 15
sex: "man"

end

Netty--Google Protobuf编解码的更多相关文章

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

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

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

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

  3. Netty游戏服务器之四protobuf编解码和黏包处理

    我们还没讲客户端怎么向服务器发送消息,服务器怎么接受消息. 在讲这个之前我们先要了解一点就是tcp底层存在粘包和拆包的机制,所以我们在进行消息传递的时候要考虑这个问题. 看了netty权威这里处理的办 ...

  4. Netty对常用编解码的支持

    参考文献:极客时间傅健老师的<Netty源码剖析与实战>Talk is cheap.show me the code! Netty对编解码的支持 打开Netty的源码,它对很多的编码器都提 ...

  5. 编解码-protobuf

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

  6. 【转】Netty系列之Netty编解码框架分析

    http://www.infoq.com/cn/articles/netty-codec-framework-analyse/ 1. 背景 1.1. 编解码技术 通常我们也习惯将编码(Encode)称 ...

  7. Netty系列之Netty编解码框架分析

    1. 背景 1.1. 编解码技术 通常我们也习惯将编码(Encode)称为序列化(serialization),它将对象序列化为字节数组,用于网络传输.数据持久化或者其它用途. 反之,解码(Decod ...

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

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

  9. netty源码解解析(4.0)-19 ChannelHandler: codec--常用编解码实现

    数据包编解码过程中主要的工作就是:在编码过程中进行序列化,在解码过程中从Byte流中分离出数据包然后反序列化.在MessageToByteEncoder中,已经解决了序列化之后的问题,ByteToMe ...

随机推荐

  1. hdu 4770 13 杭州 现场 A - Lights Against Dudely 暴力 bfs 状态压缩DP 难度:1

    Description Harry: "But Hagrid. How am I going to pay for all of this? I haven't any money.&quo ...

  2. Request header field Content-Type is not allowed by Access-Control-Allow-Headers

    今天遇到一个跨域问题记录学习下: 一.问题: 跨域请求中包含自定义header字段时,浏览器console报错. Request header field xfilesize is not allow ...

  3. QT出现 Cannot create children for a parent that is in a different thread 的解决方法:

    timer = new Timer(this);改成 timer = new Timer();就可以了. 因为你timer是属于主线程的,尽量不要在非主线程里创建新的对象并指定其对象为主线程内的对象, ...

  4. 【dlbook】正则化

    对学习算法的修改——旨在减少泛化误差而不是训练误差 显著减少方差而不过度增加偏差. [参数范数惩罚] 通常只对权重做惩罚而不对偏置做惩罚,原因是拟合偏置比拟合权重容易很多. 不同层使用不同惩罚的代价很 ...

  5. 循环中的let和const声明

    一.循环中的let声明 每次循环的时候let声明都会创建一个新变量i,并将其初始化为i的当前值,所以循环内部创建的每个函数都能得到属于他们的i的副本. 最初的: for (var i = 0 ; i ...

  6. js之购物车案例

      这里主要提供思路: 一共两个页面通过原生来实现,我们需要对cookie进行封装. 在商品列表页,我们将点击添加的商品放入一个对象中,而后将该对象放入数组中,一个对象可以说就是一个商品.在购物车页面 ...

  7. rancher下的kubernetes之一:构建标准化vmware镜像

    学习kubernetes的时候,我们需要在kubernetes环境下实战操作,然而kubernetes环境安装并不容易,现在通过rancher可以简化安装过程,咱们来实战rancher下的kubern ...

  8. slam学习

    学习内容: 数学: 线性代数,概率论, 优化理论,离散数学, 李代数, 凸优化: 算法:   概率机器人, 机器人状态估计, 深度学习,非线性优化: 工程: c/c++ , python, ros, ...

  9. >=< 在set和dict中的不同

    两个dict比较的算法是,长度>键>值,由于dict无序,所以比较的时候会自动将键对齐比较,我们不用担心这个. >>> d1 = dict(x=1, y=2) >& ...

  10. ios逆向工程-内部钩子(Method Swizzling)

    Method Swizzling(方法调配) 怎么说呢,先了解什么是钩子为什么用钩子,学过C++的朋友应该清楚,hook就是用来获得(截断/改变)底层调用的方法.这样我们可以自由的修改或者读取一些想要 ...