netty的demo

1.创建服务器端:

public class ServerMain {
    public static void run() {
        EventLoopGroup pGroup = new NioEventLoopGroup(); //线程组:用来处理网络事件处理(接受客户端连接)
        EventLoopGroup cGroup = new NioEventLoopGroup(); //线程组:用来进行网络通讯读写
        try {
            ServerBootstrap b = new ServerBootstrap();
            b.group(pGroup, cGroup)
                    //注册服务端channel
                    .channel(NioServerSocketChannel.class) 
                    //队列形式,阻塞式处理队列里的客户端请求
                    // .option(ChannelOption.SO_BACKLOG, 1024)
                    //长连接,每两小时检测心跳
                    .option(ChannelOption.SO_KEEPALIVE, true)
                    //        .handler(new LoggingHandler(LogLevel.INFO))
                    .childHandler(new ChannelInitializer<SocketChannel>() {
                        protected void initChannel(SocketChannel sc) throws Exception {
                            sc.pipeline()
                                    //添加解码ByteBuf为字符串
                                    .addLast(new StringDecoder())
                                    //编码为字符串,这样发送消息直接使用String即可
                                    //.addLast(new StringEncoder())
                                    .addLast(new ServerHandlerOne());   //服务端业务处理类
                        }
                    });
            ChannelFuture cf = null;
            cf = b.bind(8080).sync();
            cf.channel().closeFuture().sync();
        } catch (Exception e) {
            pGroup.shutdownGracefully();
            cGroup.shutdownGracefully();
            e.printStackTrace();
        }

    }

    public static void main(String[] args) {
        new Thread(
                () -> {
                    run();
                }
        ).start();

    }
}

服务端处理类:

public class ServerHandlerOne extends SimpleChannelInboundHandler<String> {

    private static int count = 0;
    
    //SimpleChannelInboundHandler带泛型的抽象处理类
    protected void channelRead0(ChannelHandlerContext ctx, String o) throws Exception {
        //避免粘包
        String[] split = o.split("&");
        Arrays.stream(split).forEach((a) -> {
            System.out.println(a);
        });
        //只读的话需要手动释放ByteBuf计数器.
        ReferenceCountUtil.release(o);
    }

    @Override
    public void channelRegistered(ChannelHandlerContext ctx) throws Exception {
        System.out.println("客户端注册" + count++);
    }

    @Override
    public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
        System.out.println("读取客户端信息完成" + count++);
    }

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

    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        System.out.println("客户端与服务器连接成功");
        super.channelActive(ctx);
        ByteBuf b = Unpooled.copiedBuffer("我是服务器".getBytes());
        ctx.writeAndFlush(b);
    }
}

 

2.客户端;

public class ClientMain {

    public static void run() {
        EventLoopGroup cGroup = new NioEventLoopGroup(); //线程组:用来进行网络通讯读写
        try {
            Bootstrap b = new Bootstrap();
            b.group(cGroup)
                    .channel(NioSocketChannel.class) //注册服务端channel
                    .option(ChannelOption.SO_KEEPALIVE, true)
                    // .handler(new LoggingHandler(LogLevel.INFO))
                    .handler(new ChannelInitializer<SocketChannel>() {
                        protected void initChannel(SocketChannel sc) throws Exception {
                            //5s没有交互,就会关闭channel
                            sc.pipeline()
                                    .addLast(new StringDecoder())
                                    .addLast(new ClientHandler())
                                    .addLast(new ClientHandler2());
                        }
                    });
            ChannelFuture localhost = b.connect("localhost", 8080);
            // localhost.addListener(ChannelFutureListener.CLOSE);
            localhost.channel().closeFuture().sync();
            System.out.println("aaaa");
        } catch (Exception e) {
            cGroup.shutdownGracefully();
            e.printStackTrace();
        }

    }

    public static void main(String[] args) {
        run();
    }
}

两个客户端处理类:

public class ClientHandler extends SimpleChannelInboundHandler<String> {

    protected void channelRead0(ChannelHandlerContext ctx, String) throws Exception {
        System.out.println(o);
        //此处使该方法中管道和信息往下传播到下一个处理类
        ctx.fireChannelRead(o);
    }

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

    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        System.out.println(1);
        //此处使该方法中管道和信息往下传播到下一个处理类
        ctx.fireChannelActive();
        new Thread(() -> {
            String s = "客户端&";
            int i = 0;
            do {
                ByteBuf b = Unpooled.buffer(s.length());
                try {
                    b.writeBytes(s.getBytes("utf-8"));
                   //注释掉间隔时间,则服务器产生粘包现象
                   // Thread.sleep(500);
                } catch (Exception e) {
                    e.printStackTrace();
                }
                ctx.writeAndFlush(b);
                i++;
            } while (i != 10);
        }).start();
    }

}
public class ClientHandler2 extends SimpleChannelInboundHandler {

    protected void channelRead0(ChannelHandlerContext ctx, Object o) throws Exception {
        System.out.println(o.toString() + 2);
    }

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

    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        System.out.println(2);

    }
}

 

注: 短连接则每次客户端发送完信息,得到服务器响应后即可关闭管道资源;长连接则可以做心跳机制检测连接情况;

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值