netty unpacking and sticking (LineBasedFrameDecoder)

Netty unpacks and sticks packets, that is, half-packet reading and writing problems.

As I said before, there are mainly three solutions, one is the fixed length of the message, the other is the separator, and the other is to divide the message into the message header message body.

When talking about delimiters before, I mainly talked about DelimiterBasedFrameDecoder . DelimiterBasedFrameDecoder can specify any delimiter. Note that its delimiter should be placed in front.

What I want to talk about today is LineBasedFrameDecoder. LineBasedFrameDecoder also belongs to the category of delimiters, but the delimiter of LineBasedFrameDecoder is limited to the newline character \n, and it is placed at the end of the message. And use with StringDecoder.

Key part 1 When configuring the handler:

 // Add unpacking and sticking decoder
 pipeline.addLast( new LineBasedFrameDecoder(1024));        
        pipeline.addLast( new StringDecoder());
 key part 2 When sending a message:

future.channel().writeAndFlush(Unpooled.copiedBuffer(("你好"+System.getProperty("line.separator")).getBytes()));
System.getProperty ( " line.separator " ) is the added separator.


There is a detail to pay attention to, that is, new LineBasedFrameDecoder(1024) What does 1024 mean here? It means that if the message length reaches 1024 and no newline is found, then it is abnormal and the message cannot be received. Therefore, this value must be greater than the length of the message, as large as possible.

See the specific code below:

Three on the server side:

import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.logging.LogLevel;
import io.netty.handler.logging.LoggingHandler;

public class LineServer {

    public void bind() {
        EventLoopGroup bossGroup = new NioEventLoopGroup();
        EventLoopGroup workGroup = new NioEventLoopGroup();
        ServerBootstrap bootstrap = new ServerBootstrap();
        bootstrap.group(bossGroup, workGroup);
        bootstrap.channel(NioServerSocketChannel.class)
                .option(ChannelOption.SO_BACKLOG, 1024)
                .option(ChannelOption.SO_SNDBUF, 32 * 1024)
                .option(ChannelOption.SO_RCVBUF, 32 * 1024)
                .option(ChannelOption.SO_KEEPALIVE, true)
                .handler(new LoggingHandler(LogLevel.DEBUG))
                .childHandler(new LineServerInitialzer());

        try {

            ChannelFuture future = bootstrap.bind("127.0.0.1", 8765).sync();
            future.channel().closeFuture().sync();
            bossGroup.shutdownGracefully();
            workGroup.shutdownGracefully();
        } catch (InterruptedException e) {
            e.printStackTrace ();
        }

    }

    public static void main(String[] args) {
        new LineServer().bind();
    }
}


import io.netty.channel.Channel;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
import io.netty.handler.codec.LineBasedFrameDecoder;
import io.netty.handler.codec.string.StringDecoder;

public class LineServerInitialzer extends ChannelInitializer {

    protected void initChannel(Channel ch) throws Exception {
        ChannelPipeline pipeline = ch.pipeline();
        //添加拆包粘包解码器
        pipeline.addLast(new LineBasedFrameDecoder(1024));
        pipeline.addLast(new StringDecoder());
        pipeline.addLast(new LineServerHandler());
    }
}



public class LineServerHandler extends ChannelHandlerAdapter {
    private Log logger= LogFactory.getLog(LineServerHandler.class);
    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        logger.error("server erro",cause);
    }

    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        logger.info("---------------server active-----------");
    }

    @Override
    public void channelInactive(ChannelHandlerContext ctx) throws Exception {
        logger.info("---------------server inActive-----------");
    }

    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        logger.info("---------------server read-----------");
        String rev_msg= (String) msg;
        logger.info("server read:"+rev_msg);

    }

    @Override
    public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
        ctx.close();
    }
}



Client端 三个

import io.netty.bootstrap.Bootstrap;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelFuture;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.logging.LogLevel;
import io.netty.handler.logging.LoggingHandler;

public class LineClient {

    public void connect(){
        EventLoopGroup workGroup=new NioEventLoopGroup();
        Bootstrap bootstrap=new Bootstrap();
        bootstrap.group(workGroup);
        bootstrap.channel(NioSocketChannel.class)
                .handler(new LineClientInitializer())
                .handler(new LoggingHandler(LogLevel.DEBUG));
        try {
        ChannelFuture future= bootstrap.connect("127.0.0.1",8765).sync();
        for(int i=0;i<10;i++){
            future.channel().writeAndFlush(Unpooled.copiedBuffer(("你好"+System.getProperty("line.separator")).getBytes()));
        }
        future.channel().closeFuture().sync();
        workGroup.shutdownGracefully();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) {
        new LineClient().connect();
    }
}

import io.netty.channel.Channel;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
import io.netty.handler.codec.LineBasedFrameDecoder;
import io.netty.handler.codec.string.StringDecoder;

public class LineClientInitializer extends ChannelInitializer {
    protected void initChannel(Channel ch) throws Exception {
        ChannelPipeline pipeline=ch.pipeline();
        pipeline.addLast(new LineBasedFrameDecoder(1024));
        pipeline.addLast(new StringDecoder());
        pipeline.addLast(new LineClientHandler());
    }
}

import io.netty.channel.ChannelHandlerAdapter;
import io.netty.channel.ChannelHandlerContext;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

public class LineClientHandler extends ChannelHandlerAdapter {
    private Log logger= LogFactory.getLog(LineClientHandler.class);
    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        logger.error("client erro",cause);
    }

    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        logger.info("---------------client active-----------");
    }

    @Override
    public void channelInactive(ChannelHandlerContext ctx) throws Exception {
        logger.info("----------------client inActive----------");
    }

    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        logger.info("----------------client read---------------");
    }

    @Override
    public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
    }
}
 


Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325443812&siteId=291194637