何为 ProtoBuf
拷贝网上的介绍,先来看看官方文档给出的定义和描述:
protocol buffers 是一种语言无关、平台无关、可扩展的序列化结构数据的方法,它可用于(数据)通信协议、数据存储等。
Protocol Buffers 是一种灵活,高效,自动化机制的结构数据序列化方法-可类比 XML,但是比 XML 更小(3 ~ 10倍)、更快(20 ~ 100倍)、更为简单。
你可以定义数据的结构,然后使用特殊生成的源代码轻松的在各种数据流中使用各种语言进行编写和读取结构数据。你甚至可以更新数据结构,而不破坏由旧数据结构编译的已部署程序。
简单来讲, ProtoBuf 是结构数据序列化[1] 方法,可简单类比于 XML[2],其具有以下特点:
语言无关、平台无关。即 ProtoBuf 支持 Java、C++、Python 等多种语言,支持多个平台
高效。即比 XML 更小(3 ~ 10倍)、更快(20 ~ 100倍)、更为简单
扩展性、兼容性好。你可以更新数据结构,而不影响和破坏原有的旧程序
序列化[1]:将结构数据或对象转换成能够被存储和传输(例如网络传输)的格式,同时应当要保证这个序列化结果在之后(可能在另一个计算环境中)能够被重建回原来的结构数据或对象。
更为详尽的介绍可参阅 维基百科。
类比于 XML[2]:这里主要指在数据通信和数据存储应用场景中序列化方面的类比,但个人认为 XML 作为一种扩展标记语言和 ProtoBuf 还是有着本质区别的。
—————————————-以上摘自网上的内容————————————-
优点:简单来说,protobuf是google的亲儿子,具有体积小,序列化快等各种优势。特别在网络传输中,体积小能节省带宽,提高传输效率等优势。
缺点:需要预编译,开发相比json等常用的数据协议略显复杂。
同样,getty提供直接可用的protobuf编解码器,并且已经处理好了黏包和拆包的工作
示例
使用protobuf,首先需要导入protobuf依赖
<dependency>
<groupId>com.google.protobuf</groupId>
<artifactId>protobuf-java</artifactId>
<version>3.8.0</version>
</dependency>
<dependency>
<groupId>com.google.protobuf</groupId>
<artifactId>protobuf-java-util</artifactId>
<version>3.8.0</version>
</dependency>
AioServerStarter server = new AioServerStarter(8888);
server.channelInitializer(new ChannelInitializer() {
@Override
public void initChannel(AioChannel channel) throws Exception {
DefaultChannelPipeline defaultChannelPipeline = channel.getDefaultChannelPipeline();
//添加protobuf编码器
defaultChannelPipeline.addLast(new ProtobufVarint32LengthFieldPrepender());
defaultChannelPipeline.addLast(new ProtobufEncoder());
//添加protobuf解码器
defaultChannelPipeline.addLast(new ProtobufVarint32FrameDecoder());
defaultChannelPipeline.addLast(new ProtobufDecoder(MessageClass.Message.getDefaultInstance()));
defaultChannelPipeline.addLast(new SimpleHandler());
}
});
server.start();
消息处理器
import com.gettyio.core.channel.AioChannel;
import com.gettyio.core.pipeline.PipelineDirection;
import com.gettyio.core.pipeline.in.SimpleChannelInboundHandler;
import com.gettyio.protobuf.packet.MessageClass;
public class SimpleHandler extends SimpleChannelInboundHandler<MessageClass.Message> {
@Override
public void channelAdded(AioChannel aioChannel) {
System.out.println("连接过来了");
}
@Override
public void channelClosed(AioChannel aioChannel) {
System.out.println("连接关闭了");
}
@Override
public void channelRead0(AioChannel aioChannel, MessageClass.Message str) {
System.out.println("读取消息:" + str.getId());
}
@Override
public void exceptionCaught(AioChannel aioChannel, Throwable cause, PipelineDirection pipelineDirection) {
System.out.println("出错了");
}
}
上面使用的Message类是通过protobuf工具生成的类。如何生成,请查看本人博客:https://blog.csdn.net/KokJuis/article/details/54094348 点击查看链接