Netty custom codec to deal with TCP sticky packet unpacking problem

Customize the codec to deal with the problem of TCP sticky packet unpacking

Specific code implementation
Custom codec
PersonProtocol
public class PersonProtocol {

    private int length;
    private byte[] content;

    public int getLength() {
        return length;
    }

    public void setLength(int length) {
        this.length = length;
    }

    public byte[] getContent() {
        return content;
    }

    public void setContent(byte[] content) {
        this.content = content;
    }
}


MyPersonDecoder
//  编写解码器
public class MyPersonDecoder extends ReplayingDecoder<Void> {
    @Override
    protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception {
         System.out.println("MyPersonDecoder decode invoked!");

         int length = in.readInt();

         byte[] content = new byte[length];
         in.readBytes(content);

         PersonProtocol personProtocol = new PersonProtocol();
         personProtocol.setLength(length);
         personProtocol.setContent(content);

         out.add(personProtocol);
    }
}



MyPersonEncoder
// Encoder
public class MyPersonEncoder extends MessageToByteEncoder<PersonProtocol> {

    @Override
    protected void encode(ChannelHandlerContext ctx, PersonProtocol msg, ByteBuf out) throws Exception {
        System.out.println("MyPersonEncoder encode invoked!");

        out.writeInt(msg.getLength());
        out.writeBytes(msg.getContent());
    }
}


服务端
MyClient
public class MyClient {
    public static void main(String[] args) throws  Exception{

        // Event thread group eventLoopGroup
        EventLoopGroup eventLoopGroup = new NioEventLoopGroup();

        try {
            Bootstrap bootstrap = new Bootstrap();  //  启动服务
            bootstrap.group(eventLoopGroup).channel(NioSocketChannel.class).
                    handler(new ChannelInitializer<SocketChannel>() {
                        @Override
                        protected void initChannel(SocketChannel ch) throws Exception {

                            ChannelPipeline pipeline= ch.pipeline();

                            pipeline.addLast(new MyPersonEncoder());
                            pipeline.addLast(new MyPersonDecoder());

                            pipeline.addLast(new MyClientHandler());
                        }
                    }); // channel initialization

            ChannelFuture channelFuture = bootstrap.connect("localhost",8899).sync();
            channelFuture.channel().closeFuture().sync();
        }finally {
            eventLoopGroup.shutdownGracefully();
        }
    }
}


MyClientHandler
public class MyClientHandler extends SimpleChannelInboundHandler<PersonProtocol> {

    private int count;
    @Override
    protected void channelRead0(ChannelHandlerContext ctx, PersonProtocol msg) throws Exception {

        int length=msg.getLength();
        byte[] content = msg.getContent();

        System.out.println("The client received the message");

        System.out.println("长度:"+length);
        System.out.println("内容:"+new String(content, Charset.forName("utf-8")));

        System.out.println("The number of messages received by the client: "+(++count));
    }

    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        for(int i=0;i<10;i++){
            String messageToBeSent = "发送自客户端";
            byte[] content = messageToBeSent.getBytes(Charset.forName("utf-8"));
            int length = messageToBeSent.getBytes(Charset.forName("utf-8")).length;

            PersonProtocol personProtocol = new PersonProtocol();
            personProtocol.setLength(length);
            personProtocol.setContent(content);

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



服务端
MyServer
public class MyServer {
    public static void main(String[]args) throws Exception{

        //Two thread groups
        EventLoopGroup bossGroup = new NioEventLoopGroup();
        EventLoopGroup workerGroup = new NioEventLoopGroup();

        try {             ServerBootstrap serverBootstrap = new ServerBootstrap();//Start the server             serverBootstrap.group(bossGroup, workerGroup).channel(NioServerSocketChannel.class)                     .handler(new LoggingHandler(LogLevel.INFO)). //Specify the log level of the log handler for bossGroup                     childHandler(new MyServerInitialzer());//Specify log level for workerGroup



            ChannelFuture channelFuture = serverBootstrap.bind(8899).sync();//Bind port
            channelFuture.channel().closeFuture().sync();
        }finally {             bossGroup.shutdownGracefully();//Close thread group             workerGroup.shutdownGracefully ();         }     } }






MyServerInitialzer

public class MyServerInitialzer extends ChannelInitializer<SocketChannel> {
    @Override
    protected void initChannel(SocketChannel ch) throws Exception {
        ChannelPipeline pipeline = ch.pipeline();

        pipeline.addLast(new MyPersonDecoder());
        pipeline.addLast(new MyPersonEncoder());

        pipeline.addLast(new MyServerHandler());
    }
}


MyServerHandler
public class MyServerHandler extends SimpleChannelInboundHandler<PersonProtocol> {
    private int count;
    @Override
    protected void channelRead0(ChannelHandlerContext ctx, PersonProtocol msg) throws Exception {

        int length = msg.getLength();
        byte[] content = msg.getContent();

        System.out.println("The server received data:");
        System.out.println("Length: "+length);
        System.out.println("Content: "+new String (content, Charset.forName( "utf-8")));

        System.out.println("The number of messages received by the server: "+(++count));

        String responseMessage= UUID.randomUUID().toString();
        int responseLength = responseMessage.getBytes("utf-8").length;
        byte[] responseContent = responseMessage.getBytes("utf-8");

        PersonProtocol personProtocol = new PersonProtocol();
        personProtocol.setContent(responseContent);
        personProtocol.setLength(responseLength);

        ctx.writeAndFlush(personProtocol);
    }

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

Guess you like

Origin blog.csdn.net/weixin_45623983/article/details/128700101