netty unpacking sticky package

There are three main solutions for tcp unpacking and sticking:

Unpacking and sticking scheme:
1. The length of the message is fixed, and the lack of space should be filled in (fill manually, it will not be filled automatically)
2. Add special characters at the end of the package for segmentation, emphasizing that it is added at the end of the package. Once the received message is disassembled in this way, it must be sent in this way, otherwise the message will not be received.
3. Divide the message into a message header and a message body, and include a field representing the length of the message in the message header, and then perform business logic processing.


package  com.aowin.netty.chaibaoAndNianbao;

import  io.netty.bootstrap.Bootstrap;
import  io.netty.buffer.ByteBuf;
import  io.netty.buffer.Unpooled;
import  io.netty.channel.ChannelFuture;
import  io.netty.channel.ChannelInitializer;
import  io.netty.channel.EventLoopGroup;
import  io.netty.channel.nio.NioEventLoopGroup;
import  io.netty.channel.socket.SocketChannel;
import  io.netty.channel.socket.nio.NioServerSocketChannel;
import  io.netty.channel.socket.nio.NioSocketChannel;
import  io.netty.handler.codec.DelimiterBasedFrameDecoder;
import  io.netty.handler.codec.FixedLengthFrameDecoder;
import  io.netty.handler.codec.string.StringDecoder; public class Client { public void connect() {         EventLoopGroup workGroup =  new NioEventLoopGroup();         Bootstrap bootstrap =  new Bootstrap();         bootstrap.group(workGroup).channel(NioSocketChannel. class)                 .handler( new ChannelInitializer<SocketChannel>() { protected void initChannel(SocketChannel socketChannel)  throws 



   




                    Exception {
                        /*//  Method 1: Add special characters to the end of the packet                         // Set the special separator                         ByteBuf f=Unpooled.copiedBuffer("$_".getBytes());                         socketChannel.pipeline().addLast(new DelimiterBasedFrameDecoder(1024, f) );*/                        // Method 2 Fixed length key class FixedLengthFrameDecoder  Each fixed length is counted as a message socketChannel.pipeline().addLast( new  FixedLengthFrameDecoder( 5 )); //5 represents a length of  5 bytes socketChannel.pipeline ().addLast( new  StringDecoder());                         socketChannel.pipeline().addLast( new 




                       
                       
ClientHandler());
                    }
                });
        try  {
            ChannelFuture f = bootstrap.connect( "127.0.0.1" 8765 ).sync();
                // f.channel().writeAndFlush(Unpooled.copiedBuffer("adbcefg".getBytes ()));// More than 5 , in fact, only adbce  can be received , and the latter cannot be received because less than 5 lengths
//f.channel ().writeAndFlush(Unpooled.copiedBuffer("adb".getBytes ()));// Less than 5 lengths, this cannot be received, f.channel().writeAndFlush(Unpooled.copiedBuffer ( " adb " .getBytes ())); // Make up for 5 lengths, can receive arrive                
               
                  f.channel().closeFuture().sync();
            workGroup.shutdownGracefully();
        }  catch  (InterruptedException e) {
            e.printStackTrace();
        }
    }

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

}

ClientHandler
package com.aowin.netty.chaibaoAndNianbao;

import com.aowin.netty.hello.ClientHanler;
import io.netty.bootstrap.Bootstrap;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandlerAdapter;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.string.StringDecoder;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;


public class ClientHandler  extends ChannelHandlerAdapter {
    private Log  logger= LogFactory. getLog(ClientHanler. class);
    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause)  throws Exception {
        ctx.close();

    }

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

    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg)  throws Exception {
        String rev_msg= (String) msg;
        logger.info( " 客户端收到的消息 ///"+rev_msg);
    }

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

Server
package com.aowin.netty.chaibaoAndNianbao;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.PooledByteBufAllocator;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.DelimiterBasedFrameDecoder;
import io.netty.handler.codec.FixedLengthFrameDecoder;
import io.netty.handler.codec.string.StringDecoder;

import java.nio.Buffer;

public class Server {
    public void bind() {
        EventLoopGroup boosGroup =  new NioEventLoopGroup();
        EventLoopGroup workGroup =  new NioEventLoopGroup();
        ServerBootstrap bootstrap =  new ServerBootstrap();
        bootstrap.group(boosGroup, workGroup)
                .channel(NioServerSocketChannel. class)
                .option(ChannelOption. SO_BACKLOG10)
                .option(ChannelOption. CONNECT_TIMEOUT_MILLIS, 2000)
                .childHandler( new ChannelInitializer<SocketChannel>() {
                    protected void initChannel(SocketChannel socketChannel)  throws Exception {
                        /*
                       // 方式一:包尾添加特殊字符
                        // 设置拆包粘包特殊字符 关键类  DelimiterBasedFrameDecoder
                        // 当客户端发来的消息每出现一个 “$_” 就算是一段消息
                        ByteBuf f = Unpooled.copiedBuffer("$_".getBytes());
                        socketChannel.pipeline().addLast(new DelimiterBasedFrameDecoder(1024, f));//1024 指的是分隔符的长度上限 */
                        // 设置字符串形式的编解码

                        // 方式二:固定长度
                        socketChannel.pipeline().addLast( new FixedLengthFrameDecoder( 5));
                        socketChannel.pipeline().addLast( new StringDecoder());
                        socketChannel.pipeline().addLast( new com.aowin.netty.chaibaoAndNianbao.ServerHandler());
                    }
                });
        try {
            ChannelFuture future = bootstrap.bind( "127.0.0.1"8765).sync();
            future.channel().closeFuture().sync();
            boosGroup.shutdownGracefully();
            workGroup.shutdownGracefully();
        }  catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

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

ServerHandler
package com.aowin.netty.chaibaoAndNianbao;

import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelHandlerAdapter;
import io.netty.channel.ChannelHandlerContext;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

public class ServerHandler  extends ChannelHandlerAdapter {
    private Log  logger = LogFactory. getLog(ServerHandler. class);

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause)  throws Exception {
        logger.error( " 服务端异常 ", cause);
        ctx.close();
    }

    @Override
    public void channelActive(ChannelHandlerContext ctx)  throws Exception {
        logger.info( " 服务端激活 ");
    }

    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg)  throws Exception {
        logger.info( " 服务端开始读数据 ");
        String rev_msg = (String) msg;
        logger.info(rev_msg);
    }

    @Override
    public void channelReadComplete( final ChannelHandlerContext ctx)  throws Exception {
        logger.info( " 服务端读完数据 ");
        ChannelFuture cf = ctx.writeAndFlush(Unpooled. copiedBuffer( "adbcefg".getBytes()));
        cf.addListener( new ChannelFutureListener() {
            public void operationComplete(ChannelFuture channelFuture)  throws Exception {
                logger.info( " 客户端收到消息 ");
                ctx.close();
            }
        });

    }
}

Guess you like

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