Netty对Java内置序列化的解决粘包/半包问题的编解码方案

性能比不过protobuf序列化协议,不过与Java有天生的亲和性

解码工具:ObjectDecoder

编码工具:ObjectEncoder

  • 代码

使用Netty对Protobuf的解决粘包/半包问题的编解码方案中的user.proto

1.JavaSerializeServer

/**
 * @author pdc
 */
public class JavaSerializeServer {

    public void bind(int port) throws Exception {
        //配置服务端的NIO线程组
        EventLoopGroup bossGroup = new NioEventLoopGroup();
        EventLoopGroup workerGroup = new NioEventLoopGroup();

        try {
            ServerBootstrap b = new ServerBootstrap();
            b.group(bossGroup, workerGroup)
                    .channel(NioServerSocketChannel.class)
                    .option(ChannelOption.SO_BACKLOG, 100)
                    .handler(new LoggingHandler(LogLevel.INFO))
                    .childHandler(new ChannelInitializer<SocketChannel>() {
                        @Override
                        protected void initChannel(SocketChannel ch) throws Exception {
                            //配置java默认序列化解码工具ObjectDecoder
                            ch.pipeline().addLast(new ObjectDecoder(100 * 1024,
                                    ClassResolvers.weakCachingConcurrentResolver(this.getClass().getClassLoader())));
                            ch.pipeline().addLast(new JavaSerializeServerHandler());
                        }
                    });
            //绑定端口,同步等待成功
            ChannelFuture f = b.bind(port).sync();
            //等待服务端监听端口关闭
            f.channel().closeFuture().sync();
        } finally {
            //优雅退出,释放线程池资源
            bossGroup.shutdownGracefully();
            workerGroup.shutdownGracefully();
        }
    }

    public static void main(String[] args) throws Exception {
        int port = 8080;
        new JavaSerializeServer().bind(port);
    }
}

2.JavaSerializeServerHandler

/**
 * @author pdc
 */
public class JavaSerializeServerHandler extends ChannelInboundHandlerAdapter {

    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        //接收客户端发送过来的消息,其中经过前面解码工具ObjectDecoder
        //的处理,将字节码消息自动转换成了UserInfo对象
        UserInfo req = (UserInfo) msg;
        System.out.println("received from client:" + req.toString());
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
        cause.printStackTrace();
        ctx.close();
    }
}

3.JavaSerializeClient

/**
 * @author pdc
 */
public class JavaSerializeClient {

    public void connect(int port, String host) throws Exception {
        // 配置客户端NIO线程组
        EventLoopGroup group = new NioEventLoopGroup();
        try {
            Bootstrap b = new Bootstrap();
            b.group(group)
                    .channel(NioSocketChannel.class)
                    .option(ChannelOption.TCP_NODELAY, true)
                    .handler(new ChannelInitializer<SocketChannel>() {
                        @Override
                        public void initChannel(SocketChannel ch) throws Exception {
                            //配置java默认序列化解码工具ObjectEncoder
                            ch.pipeline().addLast(new ObjectEncoder());
                            ch.pipeline().addLast(new JavaSerializeClientHandler());
                        }
                    });
            ChannelFuture f = b.connect(host, port).sync();
            f.channel().closeFuture().sync();
        } finally {
            group.shutdownGracefully();
        }
    }

    public static void main(String[] args) throws Exception {
        int port = 8080;
        new JavaSerializeClient().connect(port, "127.0.0.1");
    }
}

4.JavaSerializeClientHandler

/**
 * @author pdc
 */
public class JavaSerializeClientHandler extends ChannelInboundHandlerAdapter {

    @Override
    public void channelActive(ChannelHandlerContext ctx) {
        //channel建立之后,向服务端发送消息,需要注意的是这里写入的消息是完整的UserInfo对象
        //因为后续会被ObjectEncoder进行编码处理
        UserInfo user = UserInfo.newBuilder()
                .name("liyebing")
                .userId(10000)
                .email("[email protected]")
                .mobile("153****0976")
                .remark("remark info").build();

        ctx.writeAndFlush(user);
    }
    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
        cause.printStackTrace();
        ctx.close();
    }
}
  • 运行:

先运行JavaSerializeServer的main,再运行JavaSerializeClient的main即可

猜你喜欢

转载自blog.csdn.net/qq_41594698/article/details/94607707