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));
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章