Netty学习——实现简单的聊天室

一:定义服务端

定义服务端的启动代码

public static void main(String[] args) throws InterruptedException {
        //链接监听组
        EventLoopGroup boosLoop = new NioEventLoopGroup(1);
        //工作组
        EventLoopGroup workerLoop = new NioEventLoopGroup(8);

        try {
            ServerBootstrap bootstrap = new ServerBootstrap();
            //绑定两个线程组
            bootstrap.group(boosLoop, workerLoop)
                    //使用NioSocketChannel来作为通道的服务
                    .channel(NioServerSocketChannel.class)
                    //设置线程组队列的最大连接数
                    .option(ChannelOption.SO_BACKLOG,128)
                    //设置保存活动链接状态
                    .childOption(ChannelOption.SO_KEEPALIVE,true)
                    .childHandler(new ChannelInitializer<SocketChannel>() {

                        @Override
                        protected void initChannel(SocketChannel socketChannel) throws Exception {
                            //在pipeline链路中添加解码编码器
                            socketChannel.pipeline().addLast("decoder",new StringDecoder());
                            socketChannel.pipeline().addLast("encoder",new StringEncoder());
                            //在ChannelPipeline 中添加自定义的处理函数
                            socketChannel.pipeline().addLast(new MyNettyServerHandler());
                        }
                    });

            System.out.println("服务端端已经启动成功。。。。");
            ChannelFuture sync = bootstrap.bind(6666).sync();
            sync.channel().closeFuture().sync();
        }finally {
            //关闭
            boosLoop.shutdownGracefully();
            workerLoop.shutdownGracefully();
        }
    }

定义自定义的handler

public class MyNettyServerHandler extends SimpleChannelInboundHandler<String> {

    /**
     * 定义一个channel组 用于管理所有注入的channel
     * GlobalEventExecutor.INSTANCE 是一个全局事件执行器 是一个单例
     */
    private static ChannelGroup channelGroup = new DefaultChannelGroup(GlobalEventExecutor.INSTANCE);

    @Override
    public void handlerAdded(ChannelHandlerContext ctx) throws Exception {
        Channel channel = ctx.channel();
        //通知族群中的其他channel
        channelGroup.writeAndFlush("【客户端】"+channel.remoteAddress() + "加入聊天室");
        //并把当前channel加入到族群中
        channelGroup.add(ctx.channel());
    }

    /**
     * 断开连接的时候调用
     */
    @Override
    public void handlerRemoved(ChannelHandlerContext ctx) throws Exception {
        Channel channel = ctx.channel();
        //通知族群中的其他channel
        channelGroup.writeAndFlush("【客户端】"+channel.remoteAddress() + "离开聊天室");
    }

    /**
     * 处于活跃状态调用
     */
    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        System.out.println("【客户端】"+ctx.channel().remoteAddress() + "上线");
    }

    /**
     * 处于非活跃状态
     */
    @Override
    public void channelInactive(ChannelHandlerContext ctx) throws Exception {
        System.out.println("【客户端】"+ctx.channel().remoteAddress() + "下线");
    }

    /**
     * 读取客户端发来的数据 并进行转发
     */
    @Override
    protected void channelRead0(ChannelHandlerContext ctx, String msg) throws Exception {
        String s = "【客户端】"+ctx.channel().remoteAddress() + "说:" + msg;
        channelGroup.forEach(i->{
            //进行转发
            if (i != ctx.channel()){
                i.writeAndFlush(s);
            }
        });
    }

    /**
     * 发生异常的时候调用
     */
    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        System.out.println("【客户端】"+ctx.channel().remoteAddress() + "发生异常");
        ctx.channel();
    }
}

二:定义客户端

定义客户端的启动代码

 public static void main(String[] args) throws InterruptedException {

        //客户端只需要定义一个工作线程组就可以
        EventLoopGroup workerGroup = new NioEventLoopGroup();

        try {
            Bootstrap serverBootstrap = new Bootstrap();

            serverBootstrap.group(workerGroup)
                    //使用NioSocketChannel来作为通道的服务
                    .channel(NioSocketChannel.class)
                    .handler(new ChannelInitializer<SocketChannel>() {
                        @Override
                        protected void initChannel(SocketChannel socketChannel) throws Exception {
                            //在pipeline链路中添加解码编码器
                            socketChannel.pipeline().addLast("decoder",new StringDecoder());
                            socketChannel.pipeline().addLast("encoder",new StringEncoder());
                            //在ChannelPipeline 中添加自定义的处理函数
                            socketChannel.pipeline().addLast(new MyNettyClientHandler());
                        }
                    });
            ChannelFuture sync = serverBootstrap.connect("127.0.0.1", 6666).sync();
            Channel channel = sync.channel();
            System.out.println(">>>>"+channel.remoteAddress()+">>>>>>");
            //定义一个输入器  进行输入
            Scanner scanner = new Scanner(System.in);
            while (scanner.hasNextLine()){
                channel.writeAndFlush(scanner.nextLine() );
            }

        }finally {
            //关闭
            workerGroup.shutdownGracefully();
        }
    }

定义自己的处理器 handler

public class MyNettyClientHandler extends SimpleChannelInboundHandler<String> {
    @Override
    protected void channelRead0(ChannelHandlerContext ctx, String msg) throws Exception {
        System.out.println(msg);
    }
}

二:测试

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值