可以在 proto 中定义多个类,然后从中选择任意一个类,可以在 proto 中定义多个 message,然后再将多个 message 以枚举的形式供使用时选择。
二 实战 1 proto 文件MyMessage.proto
syntax = "proto2" ;
package netty.protobuf.diff ;
option optimize_for = SPEED ;
option java_package = "netty.protobuf.diff" ;
option java_outer_classname = "MyMessage" ;
message MessageData
{
enum MessageType {
PersonType = 1 ;
DogType = 2 ;
}
required MessageType Message_Type = 1 ;
oneof messageContent {
PersonData person = 2 ;
DogData dog = 3 ;
}
}
message PersonData {
optional string pname = 1 ;
optional int32 page = 2 ;
}
message DogData {
optional string dname = 1 ;
optional string dcolor = 2 ;
}
2 客户端
MyNettyClientTest
package netty.protobuf.diff;
import io.netty.bootstrap.Bootstrap;
import io.netty.channel.Channel;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioSocketChannel;
public class MyNettyClientTest {
public static void main(String[] args) {
EventLoopGroup eventLoopGroup = new NioEventLoopGroup();
try {
Bootstrap bootstrap = new Bootstrap();
bootstrap.group(eventLoopGroup)
.channel(NioSocketChannel.class)
.handler(new MyNettyClientInitializer());
Channel channel = bootstrap.connect("127.0.0.1", 8888).sync().channel();
} catch (Exception e) {
e.printStackTrace();
} finally {
eventLoopGroup.shutdownGracefully();
}
}
}
MyNettyClientInitializer
package netty.protobuf.diff; import io.netty.channel.ChannelInitializer; import io.netty.channel.ChannelPipeline; import io.netty.channel.socket.SocketChannel; import io.netty.handler.codec.protobuf.ProtobufEncoder; import io.netty.handler.codec.protobuf.ProtobufVarint32FrameDecoder; import io.netty.handler.codec.protobuf.ProtobufVarint32LengthFieldPrepender; public class MyNettyClientInitializer extends ChannelInitializer{ protected void initChannel(SocketChannel sc) throws Exception { ChannelPipeline pipeline = sc.pipeline(); pipeline.addLast("ProtobufVarint32FrameDecoder",new ProtobufVarint32FrameDecoder()) ; pipeline.addLast("ProtobufVarint32LengthFieldPrepender",new ProtobufVarint32LengthFieldPrepender()); // 用于将 MyMessage 类转为字节码 pipeline.addLast("ProtobufEncoder",new ProtobufEncoder()); // 构建 MyMessage 对象,并发送给服务端 pipeline.addLast("MyNettyClientHandler", new MyNettyClientHandler()); } }
MyNettyClientHandler
package netty.protobuf.diff; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.SimpleChannelInboundHandler; public class MyNettyClientHandler extends SimpleChannelInboundHandler3 服务端{ @Override protected void channelRead0(ChannelHandlerContext ctx, String receiveMsg) { } @Override public void channelActive(ChannelHandlerContext ctx) throws Exception { // 如果 num=1,向服务端发送 person对象,否则发送 dog 对象 int num = 1; MyMessage.MessageData message; MyMessage.MessageData.Builder messageBuilder = MyMessage.MessageData.newBuilder(); MyMessage.PersonData.Builder personBuilder = MyMessage.PersonData.newBuilder(); MyMessage.DogData.Builder dogBuilder = MyMessage.DogData.newBuilder(); if (num == 1) { // 构建 person 对象 MyMessage.PersonData person = personBuilder.setPname("zs").setPage(23).build(); message = messageBuilder.setMessageType(MyMessage.MessageData.MessageType.PersonType).setPerson(person).build(); } else { // 构建 dog 对象 MyMessage.DogData dog = dogBuilder.setDname("wc").setDcolor("red").build(); message = messageBuilder.setMessageType(MyMessage.MessageData.MessageType.DogType).setDog(dog).build(); } ctx.channel().writeAndFlush(message); } }
MyNettyServerTest
package netty.protobuf.diff;
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 MyNettyServerTest {
public static void main(String[] args) {
EventLoopGroup bossGroup = new NioEventLoopGroup();
EventLoopGroup workerGroup = new NioEventLoopGroup();
try {
// ServerBootstrap:服务端启动时的初始化操作
ServerBootstrap serverBootstrap = new ServerBootstrap();
// 将bossGroup 和 workerGroup 注册到服务端的 Channel 上,并注册一个服务端的初始化器 NettyServerInitializer
// 该初始化器中的 initChannel() 方法,会在连接被注册后立刻执行;最后将端口号绑定到 8888
ChannelFuture channelFuture = serverBootstrap.group(bossGroup, workerGroup)
.channel(NioServerSocketChannel.class)
.childHandler(new MyNettyServerInitializer()).bind(8888).sync();
channelFuture.channel().closeFuture().sync();
} catch (Exception e) {
e.printStackTrace();
} finally {
bossGroup.shutdownGracefully();
workerGroup.shutdownGracefully();
}
}
}
MyNettyServerInitializer
package netty.protobuf.diff; 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.ProtobufVarint32FrameDecoder; import io.netty.handler.codec.protobuf.ProtobufVarint32LengthFieldPrepender; public class MyNettyServerInitializer extends ChannelInitializer{ protected void initChannel(SocketChannel sc) throws Exception { ChannelPipeline pipeline = sc.pipeline(); pipeline.addLast("ProtobufVarint32FrameDecoder", new ProtobufVarint32FrameDecoder()); // 用于将 byte[] 解码为 MessageData 对象 pipeline.addLast("ProtobufDecoder", new ProtobufDecoder(MyMessage.MessageData.getDefaultInstance())); pipeline.addLast("ProtobufVarint32LengthFieldPrepender", new ProtobufVarint32LengthFieldPrepender()); // MessageData pipeline.addLast("MyNettyServerHandler", new MyNettyServerHandler()); } }
MyNettyServerHandler
package netty.protobuf.diff; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.SimpleChannelInboundHandler; // 注意,此时 SimpleChannelInboundHandler 的泛型是 MessageData 类型 public class MyNettyServerHandler extends SimpleChannelInboundHandler三 测试 1 先启动服务端 2 再启动客户端{ @Override protected void channelRead0(ChannelHandlerContext ctx, MyMessage.MessageData receiveMsg) throws Exception { MyMessage.MessageData.MessageType messageType = receiveMsg.getMessageType() ; // 判断 if(messageType == MyMessage.MessageData.MessageType.PersonType){ MyMessage.PersonData person = receiveMsg.getPerson() ; System.out.println(person.getPname()+"--" + person.getPage()); }else{ MyMessage.DogData dog = receiveMsg.getDog() ; System.out.println(dog.getDname()+"--" + dog.getDcolor()); } } }
zs--23



