先定义.proto文件,其中定义一个枚举DateType标识不同的消息类别,然后oneof定义Mymessage中的dataBody只能是Person、Dog、Cat中的一种。然后使用protobuf编译器编译,编译命令:protoc --java_out=src/main/java src/protobuf/Person.proto
syntax = "proto2";
package com.wq.protobuf;
option optimize_for = SPEED;
option java_package = "com.wq.nettyproto";
option java_outer_classname = "MyDataInfo";
message MyMessage{
enum DateType{
PersonType = 1;
DogType = 2;
CatType = 3;
}
required DateType data_type= 1;
oneof dataBody{
Person person = 2;
Dog dog = 3;
Cat cat = 4;
}
}
message Person{
optional string name = 1;
optional int32 age = 2;
optional string address = 3;
}
message Dog{
optional string name = 1;
optional int32 age = 2;
}
message Cat{
optional string name = 1;
optional string city = 2;
}
接下来是netty服务端代码:其中handler中的channelRead0中的参数为MyDataInfo.MyMessage类型,然后可以根据其中的msg.getDataType()来判断传过来的是Person、Dog、Cat然后进行处理。
package com.wq.nettyproto;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
public class MyServer {
public static void main(String[] args) {
EventLoopGroup bossGroup = new NioEventLoopGroup();
EventLoopGroup workerGroup = new NioEventLoopGroup();
try{
ServerBootstrap serverBootstrap = new ServerBootstrap();
serverBootstrap.group(bossGroup,workerGroup).
channel(NioServerSocketChannel.class).
childHandler(new MyServerInitializer());
ChannelFuture channelFuture = serverBootstrap.bind(8899).sync();
channelFuture.channel().closeFuture().sync();
}catch(Exception e){
e.printStackTrace();
}finally {
bossGroup.shutdownGracefully();
workerGroup.shutdownGracefully();
}
}
}
package com.wq.nettyproto;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.socket.SocketChannel;
import io.netty.handler.codec.protobuf.ProtobufDecoder;
import io.netty.handler.codec.protobuf.ProtobufEncoder;
import io.netty.handler.codec.protobuf.ProtobufVarint32FrameDecoder;
import io.netty.handler.codec.protobuf.ProtobufVarint32LengthFieldPrepender;
public class MyServerInitializer extends ChannelInitializer {
@Override
protected void initChannel(SocketChannel ch) throws Exception {
ChannelPipeline pipeline = ch.pipeline();
pipeline.addLast(new ProtobufVarint32FrameDecoder());
pipeline.addLast(new ProtobufDecoder(MyDataInfo.MyMessage.getDefaultInstance()));
pipeline.addLast(new ProtobufVarint32LengthFieldPrepender());
pipeline.addLast(new ProtobufEncoder());
pipeline.addLast(new MyServerHandler());
}
}
package com.wq.nettyproto;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
public class MyServerHandler extends SimpleChannelInboundHandler {
@Override
protected void channelRead0(ChannelHandlerContext ctx, MyDataInfo.MyMessage msg) throws Exception {
MyDataInfo.MyMessage.DateType dateType = msg.getDataType();
if(dateType==MyDataInfo.MyMessage.DateType.PersonType){
MyDataInfo.Person person = msg.getPerson();
System.out.println(person.getName());
System.out.println(person.getAge());
System.out.println(person.getAddress());
}else if(dateType==MyDataInfo.MyMessage.DateType.DogType){
MyDataInfo.Dog dog = msg.getDog();
System.out.println(dog.getName());
System.out.println(dog.getAge());
}else if(dateType==MyDataInfo.MyMessage.DateType.CatType){
MyDataInfo.Cat cat = msg.getCat();
System.out.println(cat.getName());
System.out.println(cat.getCity());
}
}
}
接下来是客户端:其中在handler中的channelActive中随机生成Person、Dog、Cat然后传给服务端。
package com.wq.nettyproto;
import io.netty.bootstrap.Bootstrap;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFuture;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioSocketChannel;
public class MyClient {
public static void main(String[] args) throws Exception{
EventLoopGroup eventLoopGroup = new NioEventLoopGroup();
try{
Bootstrap bootstrap = new Bootstrap();
bootstrap.group(eventLoopGroup).channel(NioSocketChannel.class).handler(new MyClientInitializer());
ChannelFuture channelFuture = bootstrap.connect("localhost",8899).sync();
channelFuture.channel().closeFuture().sync();
}catch(Exception e){
e.printStackTrace();
}finally {
eventLoopGroup.shutdownGracefully();
}
}
}
package com.wq.nettyproto;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.socket.SocketChannel;
import io.netty.handler.codec.protobuf.ProtobufDecoder;
import io.netty.handler.codec.protobuf.ProtobufEncoder;
import io.netty.handler.codec.protobuf.ProtobufVarint32FrameDecoder;
import io.netty.handler.codec.protobuf.ProtobufVarint32LengthFieldPrepender;
public class MyClientInitializer extends ChannelInitializer {
@Override
protected void initChannel(SocketChannel ch) throws Exception {
ChannelPipeline pipeline = ch.pipeline();
pipeline.addLast(new ProtobufVarint32FrameDecoder());
pipeline.addLast(new ProtobufDecoder(MyDataInfo.Person.getDefaultInstance()));
pipeline.addLast(new ProtobufVarint32LengthFieldPrepender());
pipeline.addLast(new ProtobufEncoder());
pipeline.addLast(new MyClientHandler());
}
}
package com.wq.nettyproto;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import java.util.Random;
public class MyClientHandler extends SimpleChannelInboundHandler {
@Override
protected void channelRead0(ChannelHandlerContext ctx, MyDataInfo.MyMessage msg) throws Exception {
}
@Override
public void channelActive(ChannelHandlerContext ctx) throws Exception {
int randomInt = new Random().nextInt(3);
MyDataInfo.MyMessage.Builder myMessage = null;
if(randomInt==0){
myMessage = MyDataInfo.MyMessage.newBuilder().
setDataType(MyDataInfo.MyMessage.DateType.PersonType).
setPerson(MyDataInfo.Person.newBuilder().
setName("王强").
setAge(30).
setAddress("郑州").build());
}else if (randomInt==1){
myMessage = MyDataInfo.MyMessage.newBuilder().
setDataType(MyDataInfo.MyMessage.DateType.DogType).setDog(MyDataInfo.Dog.newBuilder().setName("tomDog").setAge(2).build());
}else{
myMessage = MyDataInfo.MyMessage.newBuilder().
setDataType(MyDataInfo.MyMessage.DateType.CatType).setCat(MyDataInfo.Cat.newBuilder().setName("hellokity").setCity("香港迪士尼").build());
}
ctx.channel().writeAndFlush(myMessage);
}
}