zoukankan      html  css  js  c++  java
  • Netty对Protocol Buffer多协议的支持(八)

    Netty对Protocol Buffer多协议的支持(八)

    一.背景

      在上篇博文中笔者已经用代码演示了如何在netty中使用Protocol Buffer,然而细心的用户可能会发现一个明显的不足之处就是,我们的Handler只能处理一种特定的类型,而我们的项目中又不可能只有一种类型,那么这个问题该怎么解决了?多的不说,笔者直接上代码。

    二.代码实现

    2.1 message的编写

    syntax = "proto2";
    package com.rsy.netty.protobuf;
    option java_package = "com.rsy.netty.protobuf";
    option java_outer_classname = "DataInfo";
    
    message Datas{
        enum DataType {
            personType = 1;
            dogType = 2;
        }    
        
        required DataType data_type = 1;
        
        oneof type_data{
            Person person = 2;
            Dog dog = 3;
        }
    }
    
    message Person{
        required int32 id = 1;
        optional string name = 2;
    
        enum Gender {
            male = 1;
            female = 2;
        }
        
        optional Gender gender = 3;
    }
    
    message Dog {
        required float height = 1;
        optional string color = 2;
        optional int64 age = 3;
    }

    2.2 生成Java代码,在此不再赘述。

    2.3 服务端启动代码

    public class ServerTest {
        public static void main(String[] args) throws Exception {
            EventLoopGroup bossGroup = new NioEventLoopGroup();
            EventLoopGroup workerGroup = new NioEventLoopGroup();
            
            try{
                ServerBootstrap serverBootstrap = new ServerBootstrap();
                
                serverBootstrap.group(bossGroup, workerGroup).channel(NioServerSocketChannel.class)
                               .handler(new LoggingHandler(LogLevel.INFO))
                               .childHandler(new ServerChannelInitilizer());
                
                ChannelFuture channelFuture = serverBootstrap.bind(8989).sync();
                channelFuture.channel().closeFuture().sync();
            }finally{
                bossGroup.shutdownGracefully();
                workerGroup.shutdownGracefully();
            }
        }
    }

    2.4 服务端通道初始化代码

    public class ServerChannelInitilizer extends ChannelInitializer<SocketChannel>{
    
        @Override
        protected void initChannel(SocketChannel ch) throws Exception {
            ChannelPipeline pipeline = ch.pipeline();
            
            pipeline.addLast("protobufVarint32FrameDecoder", new ProtobufVarint32FrameDecoder());
            pipeline.addLast("protobufDecoder", new ProtobufDecoder(DataInfo.Datas.getDefaultInstance()));
            
            pipeline.addLast("protobufVarint32LengthFieldPrepender", new ProtobufVarint32LengthFieldPrepender());
            pipeline.addLast("protobufEncoder", new ProtobufEncoder());
            
            
            pipeline.addLast("serverHandler", new ServerHandler());
        }
    }

    2.5 服务端Handler代码

    public class ServerHandler extends SimpleChannelInboundHandler<DataInfo.Datas>{
    
        @Override
        protected void channelRead0(ChannelHandlerContext ctx, DataInfo.Datas msg) throws Exception {
            /**
             * 因为最先写过来的是Person
             */
            DataInfo.Person p = msg.getPerson();
            
            System.out.println(msg.getDataType().toString());
            System.out.println(p.getId());
            System.out.println(p.getGender().toString());
            System.out.println(p.getName());
            
            DataInfo.Datas data = DataInfo.Datas.newBuilder()
                                    .setDataType(DataType.dogType)
                                    .setDog(
                                            DataInfo.Dog.newBuilder()
                                            .setAge(23)
                                            .setColor("红色")
                                            .setHeight(3.5f)
                                            ).build();
            ctx.writeAndFlush(data);
        }
    }

    2.6 客户端启动代码

    public class ClientTest {
        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 ClientChannelInitializer());
                
                ChannelFuture channelFuture = bootstrap.connect("localhost", 8989).sync();
                channelFuture.channel().closeFuture().sync();
            }finally{
                eventLoopGroup.shutdownGracefully();
            }
        }
    }

    2.7 客户端通道初始化代码

    public class ClientChannelInitializer extends ChannelInitializer<SocketChannel>{
    
        @Override
        protected void initChannel(SocketChannel ch) throws Exception {
            ChannelPipeline pipeline = ch.pipeline();
            
            pipeline.addLast("protobufVarint32FrameDecoder", new ProtobufVarint32FrameDecoder());
            pipeline.addLast("protobufDecoder", new ProtobufDecoder(DataInfo.Datas.getDefaultInstance()));
            pipeline.addLast("protobufVarint32LengthFieldPrepender", new ProtobufVarint32LengthFieldPrepender());
            pipeline.addLast("protobufEncoder", new ProtobufEncoder());
            
            pipeline.addLast("clientHandler", new ClientHandler());
        }
    }

    2.8 客户端Handler处理代码

    public class ClientHandler extends SimpleChannelInboundHandler<DataInfo.Datas>{
    
        @Override
        protected void channelRead0(ChannelHandlerContext ctx, DataInfo.Datas msg) throws Exception {
            /**
             * 服务端写回来的是dog
             */
            DataInfo.Dog dog = msg.getDog();
            
            System.out.println(msg.getDataType().toString());
            System.out.println(dog.getAge());
            System.out.println(dog.getColor());
            System.out.println(dog.getHeight());
        }
        
        @Override
        public void channelActive(ChannelHandlerContext ctx) throws Exception {
            
            DataInfo.Datas data = DataInfo.Datas.newBuilder()
                                    .setDataType(DataType.personType)
                                    .setPerson(
                                                DataInfo.Person.newBuilder()
                                                .setId(23)
                                                .setGender(Gender.female)
                                                .setName("zhangsan")
                                            )
                                    .build();
            
            ctx.writeAndFlush(data);
        }
    }

    三.运行

      运行服务端启动代码,再运行客户端启动代码。

  • 相关阅读:
    pgspider sqlite mysql docker 镜像
    pgspider docker 镜像
    pgspider基于pg 的高性能数据可视化sql 集群引擎
    diesel rust orm 框架试用
    golang 条件编译
    Performance Profiling Zeebe
    bazel 学习一 简单java 项目运行
    一个好用node http keeplive agnet
    gox 简单灵活的golang 跨平台编译工具
    mailhog 作为smtp server mock工具
  • 原文地址:https://www.cnblogs.com/miller-zou/p/7045711.html
Copyright © 2011-2022 走看看