proto 文件中定义多个消息

x33g5p2x  于2022-06-06 转载在 其他  
字(6.0k)|赞(0)|评价(0)|浏览(301)

一 点睛

可以在 proto 中定义多个类,然后从中选择任意一个类,可以在 proto 中定义多个 message,然后再将多个 message 以枚举的形式供使用时选择。

二 实战

1 proto 文件

MyMessage.proto

  1. syntax = "proto2" ;
  2. package netty.protobuf.diff ;
  3. option optimize_for = SPEED ;
  4. option java_package = "netty.protobuf.diff" ;
  5. option java_outer_classname = "MyMessage" ;
  6. message MessageData
  7. {
  8. enum MessageType {
  9. PersonType = 1 ;
  10. DogType = 2 ;
  11. }
  12. required MessageType Message_Type = 1 ;
  13. oneof messageContent {
  14. PersonData person = 2 ;
  15. DogData dog = 3 ;
  16. }
  17. }
  18. message PersonData {
  19. optional string pname = 1 ;
  20. optional int32 page = 2 ;
  21. }
  22. message DogData {
  23. optional string dname = 1 ;
  24. optional string dcolor = 2 ;
  25. }

2 客户端

MyNettyClientTest

  1. package netty.protobuf.diff;
  2. import io.netty.bootstrap.Bootstrap;
  3. import io.netty.channel.Channel;
  4. import io.netty.channel.EventLoopGroup;
  5. import io.netty.channel.nio.NioEventLoopGroup;
  6. import io.netty.channel.socket.nio.NioSocketChannel;
  7. public class MyNettyClientTest {
  8. public static void main(String[] args) {
  9. EventLoopGroup eventLoopGroup = new NioEventLoopGroup();
  10. try {
  11. Bootstrap bootstrap = new Bootstrap();
  12. bootstrap.group(eventLoopGroup)
  13. .channel(NioSocketChannel.class)
  14. .handler(new MyNettyClientInitializer());
  15. Channel channel = bootstrap.connect("127.0.0.1", 8888).sync().channel();
  16. } catch (Exception e) {
  17. e.printStackTrace();
  18. } finally {
  19. eventLoopGroup.shutdownGracefully();
  20. }
  21. }
  22. }

MyNettyClientInitializer

  1. package netty.protobuf.diff;
  2. import io.netty.channel.ChannelInitializer;
  3. import io.netty.channel.ChannelPipeline;
  4. import io.netty.channel.socket.SocketChannel;
  5. import io.netty.handler.codec.protobuf.ProtobufEncoder;
  6. import io.netty.handler.codec.protobuf.ProtobufVarint32FrameDecoder;
  7. import io.netty.handler.codec.protobuf.ProtobufVarint32LengthFieldPrepender;
  8. public class MyNettyClientInitializer extends ChannelInitializer<SocketChannel> {
  9. protected void initChannel(SocketChannel sc) throws Exception {
  10. ChannelPipeline pipeline = sc.pipeline();
  11. pipeline.addLast("ProtobufVarint32FrameDecoder",new ProtobufVarint32FrameDecoder()) ;
  12. pipeline.addLast("ProtobufVarint32LengthFieldPrepender",new ProtobufVarint32LengthFieldPrepender());
  13. // 用于将 MyMessage 类转为字节码
  14. pipeline.addLast("ProtobufEncoder",new ProtobufEncoder());
  15. // 构建 MyMessage 对象,并发送给服务端
  16. pipeline.addLast("MyNettyClientHandler", new MyNettyClientHandler());
  17. }
  18. }

MyNettyClientHandler

  1. package netty.protobuf.diff;
  2. import io.netty.channel.ChannelHandlerContext;
  3. import io.netty.channel.SimpleChannelInboundHandler;
  4. public class MyNettyClientHandler extends SimpleChannelInboundHandler<String> {
  5. @Override
  6. protected void channelRead0(ChannelHandlerContext ctx, String receiveMsg) {
  7. }
  8. @Override
  9. public void channelActive(ChannelHandlerContext ctx) throws Exception {
  10. // 如果 num=1,向服务端发送 person对象,否则发送 dog 对象
  11. int num = 1;
  12. MyMessage.MessageData message;
  13. MyMessage.MessageData.Builder messageBuilder = MyMessage.MessageData.newBuilder();
  14. MyMessage.PersonData.Builder personBuilder = MyMessage.PersonData.newBuilder();
  15. MyMessage.DogData.Builder dogBuilder = MyMessage.DogData.newBuilder();
  16. if (num == 1) {
  17. // 构建 person 对象
  18. MyMessage.PersonData person = personBuilder.setPname("zs").setPage(23).build();
  19. message = messageBuilder.setMessageType(MyMessage.MessageData.MessageType.PersonType).setPerson(person).build();
  20. } else {
  21. // 构建 dog 对象
  22. MyMessage.DogData dog = dogBuilder.setDname("wc").setDcolor("red").build();
  23. message = messageBuilder.setMessageType(MyMessage.MessageData.MessageType.DogType).setDog(dog).build();
  24. }
  25. ctx.channel().writeAndFlush(message);
  26. }
  27. }

3 服务端

MyNettyServerTest

  1. package netty.protobuf.diff;
  2. import io.netty.bootstrap.ServerBootstrap;
  3. import io.netty.channel.ChannelFuture;
  4. import io.netty.channel.EventLoopGroup;
  5. import io.netty.channel.nio.NioEventLoopGroup;
  6. import io.netty.channel.socket.nio.NioServerSocketChannel;
  7. public class MyNettyServerTest {
  8. public static void main(String[] args) {
  9. EventLoopGroup bossGroup = new NioEventLoopGroup();
  10. EventLoopGroup workerGroup = new NioEventLoopGroup();
  11. try {
  12. // ServerBootstrap:服务端启动时的初始化操作
  13. ServerBootstrap serverBootstrap = new ServerBootstrap();
  14. // 将bossGroup 和 workerGroup 注册到服务端的 Channel 上,并注册一个服务端的初始化器 NettyServerInitializer
  15. // 该初始化器中的 initChannel() 方法,会在连接被注册后立刻执行;最后将端口号绑定到 8888
  16. ChannelFuture channelFuture = serverBootstrap.group(bossGroup, workerGroup)
  17. .channel(NioServerSocketChannel.class)
  18. .childHandler(new MyNettyServerInitializer()).bind(8888).sync();
  19. channelFuture.channel().closeFuture().sync();
  20. } catch (Exception e) {
  21. e.printStackTrace();
  22. } finally {
  23. bossGroup.shutdownGracefully();
  24. workerGroup.shutdownGracefully();
  25. }
  26. }
  27. }

MyNettyServerInitializer

  1. package netty.protobuf.diff;
  2. import io.netty.channel.ChannelInitializer;
  3. import io.netty.channel.ChannelPipeline;
  4. import io.netty.channel.socket.SocketChannel;
  5. import io.netty.handler.codec.protobuf.ProtobufDecoder;
  6. import io.netty.handler.codec.protobuf.ProtobufVarint32FrameDecoder;
  7. import io.netty.handler.codec.protobuf.ProtobufVarint32LengthFieldPrepender;
  8. public class MyNettyServerInitializer extends ChannelInitializer<SocketChannel> {
  9. protected void initChannel(SocketChannel sc) throws Exception {
  10. ChannelPipeline pipeline = sc.pipeline();
  11. pipeline.addLast("ProtobufVarint32FrameDecoder", new ProtobufVarint32FrameDecoder());
  12. // 用于将 byte[] 解码为 MessageData 对象
  13. pipeline.addLast("ProtobufDecoder", new ProtobufDecoder(MyMessage.MessageData.getDefaultInstance()));
  14. pipeline.addLast("ProtobufVarint32LengthFieldPrepender", new ProtobufVarint32LengthFieldPrepender());
  15. // MessageData
  16. pipeline.addLast("MyNettyServerHandler", new MyNettyServerHandler());
  17. }
  18. }

MyNettyServerHandler

  1. package netty.protobuf.diff;
  2. import io.netty.channel.ChannelHandlerContext;
  3. import io.netty.channel.SimpleChannelInboundHandler;
  4. // 注意,此时 SimpleChannelInboundHandler 的泛型是 MessageData 类型
  5. public class MyNettyServerHandler extends SimpleChannelInboundHandler<MyMessage.MessageData> {
  6. @Override
  7. protected void channelRead0(ChannelHandlerContext ctx, MyMessage.MessageData receiveMsg) throws Exception {
  8. MyMessage.MessageData.MessageType messageType = receiveMsg.getMessageType() ;
  9. // 判断
  10. if(messageType == MyMessage.MessageData.MessageType.PersonType){
  11. MyMessage.PersonData person = receiveMsg.getPerson() ;
  12. System.out.println(person.getPname()+"--" + person.getPage());
  13. }else{
  14. MyMessage.DogData dog = receiveMsg.getDog() ;
  15. System.out.println(dog.getDname()+"--" + dog.getDcolor());
  16. }
  17. }
  18. }

三 测试

1 先启动服务端

2 再启动客户端

zs--23

相关文章