聊天室Server端

Server主类

public class NettyServer {

    public static void main(String[] args) {
        NioEventLoopGroup bossGroup = new NioEventLoopGroup(1);
        NioEventLoopGroup workerGroup = new NioEventLoopGroup();

        ServerBootstrap serverBootstrap = new ServerBootstrap();

        serverBootstrap.group(bossGroup, workerGroup)
            .channel(NioServerSocketChannel.class)
            .option(ChannelOption.SO_BACKLOG, 1024)
            .childHandler(new ChannelInitializer<SocketChannel>() {
                @Override
                protected void initChannel(SocketChannel ch) throws Exception {
                    ch.pipeline().addLast("decoder", new StringDecoder());
                    ch.pipeline().addLast("encoder", new StringEncoder());
                    ch.pipeline().addLast(new ServerInboundHandler());
                }
            });

        ChannelFuture channelFuture;
        try {
            channelFuture = serverBootstrap.bind(3000).sync();
            channelFuture.channel().closeFuture().sync();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            bossGroup.shutdownGracefully();
            workerGroup.shutdownGracefully();
        }
    }
}

ChannelHandler

public class ServerInboundHandler extends ChannelInboundHandlerAdapter {

    ChannelGroup channelGroup = ChannelGroupUtil.channelGroup;

    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        Channel channel = ctx.channel();
        channelGroup.writeAndFlush(channel.remoteAddress() + "-上线了");
        System.out.println(channel.remoteAddress() + "-上线了");
        channelGroup.add(channel);
    }

    @Override
    public void channelInactive(ChannelHandlerContext ctx) throws Exception {
        Channel channel = ctx.channel();
        System.out.println(channel.remoteAddress() + "-下线了");
        channelGroup.remove(channel);
        channelGroup.writeAndFlush(channel.remoteAddress() + "-下线了");
    }

    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        Channel currentChannel = ctx.channel();
        System.out.println(currentChannel.remoteAddress() + "说: " + msg);
        channelGroup.forEach(channel -> {
            if (channel != currentChannel) {
                channel.writeAndFlush(currentChannel.remoteAddress() + "说: " + msg);
            }
        });
    }

    @Override
    public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
        //
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        Channel channel = ctx.channel();
        channelGroup.remove(channel);
        channel.closeFuture().sync();
    }
}

ChannelGroupUtil

public class ChannelGroupUtil {

    public static ChannelGroup channelGroup = new DefaultChannelGroup(new DefaultEventExecutor());
}

聊天室Client端

Client主类

public class NettyClient {

    public static void main(String[] args) {
        NioEventLoopGroup workers = new NioEventLoopGroup();
        Bootstrap bootstrap = new Bootstrap();
        bootstrap.group(workers)
            .channel(NioSocketChannel.class)
            .handler(new ChannelInitializer<SocketChannel>() {
                @Override
                protected void initChannel(SocketChannel ch) throws Exception {
                    ch.pipeline().addLast("decoder", new StringDecoder());
                    ch.pipeline().addLast("encoder", new StringEncoder());
                    ch.pipeline().addLast(new ClientInboundHandler());
                }
            });

        ChannelFuture channelFuture;
        try {
            channelFuture = bootstrap.connect("127.0.0.1", 3000).sync();

            Scanner scanner = new Scanner(System.in);
            while (scanner.hasNextLine()) {
                String line = scanner.nextLine();
                channelFuture.channel().writeAndFlush(line);
            }

            channelFuture.channel().closeFuture();
        } catch (InterruptedException e) {
            //
        } finally {
            workers.shutdownGracefully();
        }
    }
}

ChannelHandler

public class ClientInboundHandler extends ChannelInboundHandlerAdapter {

    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        System.out.println(msg);
    }
}