Protobuf集成Netty并且多协议消息传递
Protocol buffers are a language-neutral, platform-neutral extensible mechanism for serializing
最近在学习google的protoBuf,大概的瞅了瞅[官网地址](https://developers.google.cn/protocol-buffers)写了一个入门的小程序。
- 首先去github上下载protobuf的Compiler ,下载地址
- 下载完成之后解压,然后配置环境变量,输入proto --version ,看到版本信息就代表安装成功
- 接着在idea中编写.proto文件
`
syntax = "proto2";
package tutorial;
option java_package = "com.example.msg";
option java_outer_classname = "Message";
message Notice {
enum Type {
HomeMsg = 1;
WorkMsg = 2;
}
required Type dataType = 3;
oneof body {
HomeMessage homeMsg = 4;
WorkMessage workMsg = 5;
}
}
message HomeMessage {
optional int32 id = 1;
optional string body = 2;
optional string home = 3;
}
message WorkMessage {
optional int32 id = 1;
optional string body = 2;
optional string work = 3;
}
`
-
导入相关的依赖,注意:protobuf的版本和安装的Compiler 版本保持一致,否则生成的java文件会报错
-
使用protoc --java_out=src/main/java src/proto/message.proto向指定的路径生成java文件
-
编写netty服务端程序
6.1服务端启动类
public class App {
public static void main(String[] args) throws Exception {
EventLoopGroup boss = new NioEventLoopGroup();
EventLoopGroup work = new NioEventLoopGroup();
ServerBootstrap serverBootstrap = new ServerBootstrap();
try {
serverBootstrap.group(boss,work).channel(NioServerSocketChannel.class).childHandler(new ServerInitainazer());
ChannelFuture future = serverBootstrap.bind(8899).sync();
ChannelFuture sync = future.channel().closeFuture().sync();
}catch (Exception e){
e.printStackTrace();
boss.shutdownGracefully();
work.shutdownGracefully();
}
}
}
6.2服务端ServerInitializer
public class ServerInitializer extends ChannelInitializer<SocketChannel> {
@Override
protected void initChannel(SocketChannel socketChannel) throws Exception {
ChannelPipeline pipeline = socketChannel.pipeline();
pipeline.addLast(new ProtobufVarint32FrameDecoder());
pipeline.addLast(new ProtobufDecoder(Message.Notice.getDefaultInstance()));
pipeline.addLast(new ProtobufVarint32LengthFieldPrepender());
pipeline.addLast(new ProtobufEncoder());
pipeline.addLast(new ServerHandler());
}
}
6.3服务端handler
public class ServerHandler extends SimpleChannelInboundHandler<Message.Notice> {
@Override
protected void channelRead0(ChannelHandlerContext channelHandlerContext, Message.Notice notice) throws Exception {
Message.Notice.Type dataType = notice.getDataType();
if(dataType == Message.Notice.Type.HomeMsg){
System.out.println("----------homeMsg------------");
System.out.println(notice.getHomeMsg().getId());
System.out.println(notice.getHomeMsg().getBody());
System.out.println(notice.getHomeMsg().getHome());
}else if(dataType == Message.Notice.Type.WorkMsg){
System.out.println("----------workMsg------------");
System.out.println(notice.getWorkMsg().getId());
System.out.println(notice.getWorkMsg().getBody());
System.out.println(notice.getWorkMsg().getWork());
}
}
}
-
编写netty客户端
7.1客户端启动类
public class ClientApp {
public static void main(String[] args) throws Exception {
EventLoopGroup eventExecutors = new NioEventLoopGroup();
Bootstrap bootstrap = new Bootstrap();
bootstrap.group(eventExecutors).channel(NioSocketChannel.class).handler(new ClientInitializer());
ChannelFuture future = bootstrap.connect("127.0.0.1", 8899).sync();
future.channel().closeFuture().sync();
}
}
7.2客户端ClientInitializer
public class ClientInitializer extends ChannelInitializer<SocketChannel> {
@Override
protected void initChannel(SocketChannel socketChannel) throws Exception {
ChannelPipeline pipeline = socketChannel.pipeline();
pipeline.addLast(new ProtobufVarint32LengthFieldPrepender());
pipeline.addLast(new ProtobufDecoder(Message.Notice.getDefaultInstance()));
pipeline.addLast(new ProtobufVarint32FrameDecoder());
pipeline.addLast(new ProtobufEncoder());
pipeline.addLast(new ClientHandler());
}
}
7.3 客户端handler
public class ClientHandler extends SimpleChannelInboundHandler<Message.Notice> {
@Override
protected void channelRead0(ChannelHandlerContext channelHandlerContext, Message.Notice notice) throws Exception {
}
@Override
public void channelActive(ChannelHandlerContext ctx) throws Exception {
for(int i = 0; i < 100; i++){
Message.Notice notice = null;
if(i%2==0){
Message.HomeMessage build = Message.HomeMessage.newBuilder().setBody("家庭消息主题").setHome("home").setId(i).build();
notice = Message.Notice.newBuilder().setDataType(Message.Notice.Type.HomeMsg).setHomeMsg(build).build();
}else if(i%2==1){
Message.WorkMessage build = Message.WorkMessage.newBuilder().setBody("工作消息主题").setWork("work").setId(i).build();
notice = Message.Notice.newBuilder().setDataType(Message.Notice.Type.WorkMsg).setWorkMsg(build).build();
}
ctx.channel().writeAndFlush(notice);
}
}
}
- 整体项目结构
- 运行结果