netty常用代码

一. Server

public class TimeServer_argu {

    public void bind(int port) throws InterruptedException {
        EventLoopGroup bossGroup = new NioEventLoopGroup();    // 默认开启cpu个数*2个线程
        EventLoopGroup workerGroup = new NioEventLoopGroup();
        try {
            ServerBootstrap server = new ServerBootstrap();
            server.group(bossGroup, workerGroup)
                    .channel(NioServerSocketChannel.class)
                    .option(ChannelOption.SO_BACKLOG, 128)
                    .childOption(ChannelOption.SO_KEEPALIVE, true)
                    .handler(new LoggingHandler(LogLevel.INFO))
                    .childHandler(new ChannelInitializer<SocketChannel>() {
                        @Override
                        public void initChannel(SocketChannel ch) throws Exception {
                            /* LengthFieldBasedFrameDecoder解码器, 负责解码特定格式报文(开头几个字节表示报文长度), 这个报文长度可以是
                            1. 后面真正报文的长度
                            2. 也可以是算上长度字段的报文总长度 (此时补偿字段为负)
                            */
                            // 报文最大长度,长度字段开始位置偏移量,长度字段所占长度,报文长度的补偿值(netty解析报文首部的长度值,用这个值+补偿值是真正报文的长度),真正报文开始位置的偏移量
                            ch.pipeline().addLast("frameDecoder", new LengthFieldBasedFrameDecoder(Integer.MAX_VALUE, 0, 4, 0, 4));
                            /*
                            LengthFieldPrepender编码器: netty把真正报文转换成Bytebuf发送,这个编码器在Bytebuf的开头加上真正报文的长度
                             发送方使用这个编码器,接收方就要使用LengthFieldBasedFrameDecoder解码器来解得真正报文
                             */
                            ch.pipeline().addLast("frameEncoder", new LengthFieldPrepender(4));
                            // 用于序列化反序列化对象
                            //ch.pipeline().addLast("encode", new ObjectEncoder());
                            // ClassResolvers.weakCachingConcurrentResolver(null)通常用于创建weakhashmap缓存classloader,但ocgi动态替换class,不建议缓存classloader,索引传入null
                            //ch.pipeline().addLast("decode", new ObjectDecoder(ClassResolvers.weakCachingConcurrentResolver(null)));
                            ch.pipeline().addLast(new StringDecoder());
                            ch.pipeline().addLast(new EchoServerHandler());
                       }
                    });

            ChannelFuture channel = server.bind(port).sync();
            channel.channel().closeFuture().sync();
         } finally {
            workerGroup.shutdownGracefully();
            bossGroup.shutdownGracefully();
        }
    }

    private class EchoServerHandler extends ChannelHandlerAdapter {
        @Override
        public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
            String str = (String) msg;
            System.out.println("recieve:"+str);
            str = new StringBuilder().append("server recieve ").toString();
            ByteBuf byteBuf = Unpooled.copiedBuffer(str.getBytes());
            ctx.writeAndFlush(byteBuf);
        }

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

    public static void main(String[] args) throws InterruptedException {
        new TimeServer_argu().bind(8011);
    }
}

二. Client

public class TimeClient_argu {
    private static Logger logger = LoggerFactory.getLogger("timeclient-argu");

    public static void main(String[] args) {
        new TimeClient_argu().connect(8011,"localhost");
    }

    public void connect(int port,String host){
        EventLoopGroup group = new NioEventLoopGroup();
        try{
            Bootstrap bs = new Bootstrap();
            bs.group(group).channel(NioSocketChannel.class)
                    .option(ChannelOption.TCP_NODELAY,true)
                    .handler(new ChannelInitializer<SocketChannel>() {
                        @Override
                        protected void initChannel(SocketChannel ch) throws Exception { // netty自动识别编码器和解码器放到输入和读取阶段
                            ch.pipeline().addLast("frameDecoder", new LengthFieldBasedFrameDecoder(Integer.MAX_VALUE, 0, 4, 0, 4));
                            ch.pipeline().addLast("frameEncoder", new LengthFieldPrepender(4));
                            ch.pipeline().addLast(new StringDecoder());
                            ch.pipeline().addLast(new EchoClientHandler());   // 打印回显信息
                        }
                    });
            //发起异步操作链接
            ChannelFuture f = bs.connect(host,port).sync();
            f.awaitUninterruptibly(10, TimeUnit.SECONDS);
            if (!f.isSuccess()) {   // 连接不成功记录错误日志
                logger.error(f.cause().getMessage());
            } else {
                f.channel().writeAndFlush(Unpooled.copiedBuffer("query time".getBytes()));
                f.channel().closeFuture().sync();
            }
            f.channel().closeFuture().sync();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            group.shutdownGracefully();
        }
    }

    private class EchoClientHandler extends ChannelHandlerAdapter {
        private int counter;
        // 发出的请求报文必须带有"\n"或"\r\n",否则服务端的LineBasedFrameDecoder无法解析
        private byte[] req = ("query time").getBytes();

        @Override
        public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
            String body = (String) msg;
            System.out.println("Now : "+ body + "the counter is "+ ++counter);
        }


        /*@Override
           链接成功后自动发送消息
        public void channelActive(ChannelHandlerContext ctx) throws Exception {
            ByteBuf msg = null;
            for (int i = 0; i < 10; i++) {
                msg = Unpooled.buffer(req.length);  // 创建指定长度的buf
                msg.writeBytes(req);
                ctx.writeAndFlush(msg);
            }
        }*/

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

}

转载于:https://www.cnblogs.com/72808ljup/p/5325863.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值