Netty使用分隔符和定长解码器

这里写自定义目录标题

使用分隔符解码器

服务端

import io.netty.bootstrap.*;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.*;
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.string.StringDecoder;

public class Server {

    public void bind(int port) {
        //1、创建线程池,服务端创建连个线程池
        NioEventLoopGroup boosGroup = new NioEventLoopGroup();
        NioEventLoopGroup workerGroup = new NioEventLoopGroup();
        //2、创建服务端启动对象
        ServerBootstrap bootstrap = new ServerBootstrap();
        //3、配置启动对象
        bootstrap.group(boosGroup, workerGroup) //4、添加线程池
                .channel(NioServerSocketChannel.class) //5、使用 NioServerSocketChannel 作为服务器 端通道实现
                .option(ChannelOption
                        .SO_BACKLOG, 128) //6、设置线程队列中等待连接的个数
                .childOption(ChannelOption.SO_KEEPALIVE, true) //7、保持活动状态连接
                .childHandler(new ChannelInitializer<SocketChannel>() { //8、创建一个通道初始化对象
                    @Override
                    protected void initChannel(SocketChannel socketChannel) throws Exception {
                        ChannelPipeline pipeline = socketChannel.pipeline();//9、往 Pipeline 链中添加自定义的业务 处理 handler
                        ByteBuf delimiter = Unpooled.copiedBuffer("$_".getBytes());
                        //10、添加分隔符解码器(指定$_为分隔符,如果超过1024个字迹未找到分隔符将会报错)
                        pipeline.addLast(new DelimiterBasedFrameDecoder(1024, delimiter));
                        //11、添加字符转解码器,将消息转为字符串
                        pipeline.addLast(new StringDecoder());
                        //12、添加自定义的处理类
                        pipeline.addLast(new EchoServerHandler());
                    }
                });
        try {
            //13、启动服务器端并绑定端口,等待接受客户端连接(bind为非阻塞,sync为阻塞式的)
            ChannelFuture channelFuture = bootstrap.bind(port).sync();
            System.out.println("------Server is ready------");
            //14、关闭通道(closeFuture为非阻塞,sync为阻塞式的)
            channelFuture.channel().closeFuture().sync();
        } catch (Exception e) {
            e.printStackTrace();
            System.out.println("------Chat Server is close------");
        } finally {
            boosGroup.shutdownGracefully();
            workerGroup.shutdownGracefully();
        }
    }

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

    class EchoServerHandler extends SimpleChannelInboundHandler<String>{

        int count = 0;

        protected void channelRead0(ChannelHandlerContext ctx, String msg) throws Exception {
            String body = (String)msg;
            System.out.println("This is "+ ++count + "times receive client : ["+ body + "]");
            body += "$_";
            ByteBuf echo = Unpooled.copiedBuffer(body.getBytes());
            ctx.writeAndFlush(echo);
        }

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

客户端

import io.netty.bootstrap.Bootstrap;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.codec.DelimiterBasedFrameDecoder;
import io.netty.handler.codec.string.StringDecoder;


public class Client {

   public void connect(int port,String host){
       //初始化线程池
       NioEventLoopGroup group = new NioEventLoopGroup();
       //创建启动器
       Bootstrap bootstrap = new Bootstrap();
       //配置启动器
       bootstrap.group(group)
               .channel(NioSocketChannel.class)
               .option(ChannelOption.TCP_NODELAY,true)
               .handler(new ChannelInitializer<SocketChannel>() {
                   @Override
                   protected void initChannel(SocketChannel socketChannel) throws Exception {
                       ChannelPipeline pipeline = socketChannel.pipeline();//9、往 Pipeline 链中添加自定义的业务 处理 handler
                       ByteBuf delimiter = Unpooled.copiedBuffer("$_".getBytes());
                       //10、添加分隔符解码器(指定$_为分隔符,如果超过1024个字迹未找到分隔符将会报错)
                       pipeline.addLast(new DelimiterBasedFrameDecoder(1024, delimiter));
                       //11、添加字符转解码器,将消息转为字符串
                       pipeline.addLast(new StringDecoder());
                       //添加自定义的处理类
                       pipeline.addLast(new EchoClientHandler());
                   }
               });
       try{
           ChannelFuture channelFuture = bootstrap.connect(host, port).sync();
           channelFuture.channel().closeFuture().sync();
       }catch (Exception e){
           System.out.println("连接异常");
       }
   }

    public static void main(String[] args) {
        new Client().connect(9999,"127.0.0.1");
    }

    class EchoClientHandler extends SimpleChannelInboundHandler<String>{
       private int counter;

       static final String ECHO_REQ = "Hi,Ni hao,Welcome to Netty.$_";

        protected void channelRead0(ChannelHandlerContext channelHandlerContext, String o) throws Exception {
            System.out.println(++counter+":"+o);
        }

        @Override
        public void channelActive(ChannelHandlerContext ctx) throws Exception {
            for(int i=0;i<10;i++){
                ctx.writeAndFlush(Unpooled.copiedBuffer(ECHO_REQ.getBytes()));
            }
        }
    }
}

定长解码器:

//每次按照20个字符进行解码,如果是半包消息,会缓存半包消息并等待下一个半包进行拼包
pipeline.addLast(new FixedLengthFrameDecoder(20));
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章