netty实现简易聊天室

文章目录

  • 前言
  • 一、聊天室客户端(ChatClient)
    • 2.客户端自定义handler处理器
    • 3.聊天室服务端(ChatServer)
    • 3.服务端handler处理器
  • 结果展示


前言

本人最近在学习netty,所以使用netty实现了个简易的聊天室,接下来会更新关于netty相关的内容


一、聊天室客户端(ChatClient)

/**
 * @author zwz
 * @date 2022/5/23 上午8:54
 */
public class ChatClient {
    public static void main(String[] args) throws InterruptedException {
        NioEventLoopGroup workGroup = new NioEventLoopGroup();
        Bootstrap bootstrap = new Bootstrap();
        bootstrap.group(workGroup);
        bootstrap.channel(NioSocketChannel.class);
        // 设置处理器
        bootstrap.handler(new ChannelInitializer<NioSocketChannel>() {
            @Override
            protected void initChannel(NioSocketChannel ch) throws Exception {
                // 将字符串编解码器及客户端处理器添加到pipeline中
                ch.pipeline().addLast(new StringDecoder(CharsetUtil.UTF_8));
                ch.pipeline().addLast(new StringEncoder(CharsetUtil.UTF_8));
                ch.pipeline().addLast(new ChatClientHandler());
            }
        });
        // 连接服务端
        ChannelFuture channelFuture = bootstrap.connect("127.0.0.1", 9000);
        channelFuture.sync();
        // 获取客户端输入的内容,并发送至服务端(因为添加了字符串编解码器,所以此处可以直接发送字符串)
        Scanner scanner = new Scanner(System.in);
        while (scanner.hasNextLine()) {
            channelFuture.channel().writeAndFlush(scanner.nextLine());
        }
    }
}

2.客户端自定义handler处理器

此处只做了基本的打印逻辑

/**
 * @author zwz
 * @date 2022/5/23 上午8:55
 */
public class ChatClientHandler extends ChannelInboundHandlerAdapter {
    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        System.out.println(msg.toString());
    }
}

3.聊天室服务端(ChatServer)

/**
 * @author zwz
 * @date 2022/5/23 上午8:54
 */
public class ChatServer {
    public static void main(String[] args) {
        // 新建两个事件循环组,这个后续的文章会介绍
        NioEventLoopGroup bossGroup = new NioEventLoopGroup();
        NioEventLoopGroup workGroup = new NioEventLoopGroup();

        ServerBootstrap serverBootstrap = new ServerBootstrap();
        serverBootstrap.group(bossGroup, workGroup);
        serverBootstrap.channel(NioServerSocketChannel.class);
        serverBootstrap.childHandler(new ChannelInitializer<NioSocketChannel>() {
            @Override
            protected void initChannel(NioSocketChannel ch) throws Exception {
                ch.pipeline().addLast(new StringEncoder(CharsetUtil.UTF_8));
                ch.pipeline().addLast(new StringDecoder(CharsetUtil.UTF_8));
                ch.pipeline().addLast(new ChatServerHandler());
            }
        });
        // 服务端绑定9000端口
        serverBootstrap.bind(9000);
    }
}

3.服务端handler处理器

/**
 * @author zwz
 * @date 2022/5/23 上午8:55
 */
public class ChatServerHandler extends ChannelInboundHandlerAdapter {

	// 创建一个list集合存储连接上的所有客户端channel
    private static List<Channel> channels = new ArrayList<>();

   // 当有客户端连接上服务端,底层会调用此方法,执行此方法的逻辑
   // 这里大概的处理逻辑是:先添加新客户端channel到集合中,然后循环遍历list集合
   // 然后根据不同的channel发送不同的系统消息
    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        Channel channel = ctx.channel();
        channels.add(channel);
        channels.forEach(ch -> {
            if (ch == channel) {
                channel.writeAndFlush("恭喜您,上线成功");
            } else {
                ch.writeAndFlush("系统消息:[" + ch.remoteAddress() + "]客户端已上线");
            }
        });
        System.out.println("客户端[" + channel.remoteAddress() + "]请求连接");
    }

   // 当有客户端连断开连接,底层会调用此方法,执行此方法的逻辑
   // 这里大概的处理逻辑是:然后循环遍历list集合,找到已断开连接的channel并删除
   // 向集合内的channel发送系统消息
    @Override
    public void channelInactive(ChannelHandlerContext ctx) throws Exception {
        Channel channel = ctx.channel();
        Iterator<Channel> iterator = channels.iterator();
        while (iterator.hasNext()) {
            Channel ch = iterator.next();
            if (ch == channel) {
                iterator.remove();
            }
            ch.writeAndFlush("系统消息:[" + channel.remoteAddress() + "]客户端已下线");
        }
        System.out.println("客户端[" + channel.remoteAddress() + "]断开连接");
    }

   // 当有客户端发送消息到服务端,底层会调用此方法,执行此方法的逻辑
   // 这里大概的处理逻辑是:循环遍历向集合中的channel(除发送消息的客户端)发送消息
    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        Channel channel = ctx.channel();
        System.out.println("服务端收到客户端[" + channel.remoteAddress() + "]发来的消息:" + msg.toString());

        String now = DateUtil.now();
        channels.forEach(ch -> {
            if (ch != channel) {
                ch.writeAndFlush("消息时间:" + now + " 用户[" + channel.remoteAddress() + "]说:" + msg.toString());
            }
        });
    }

}

结果展示

1.chatServer控制台输出:
netty实现简易聊天室_第1张图片

2.客户端127.0.0.1:55408控制台输出
netty实现简易聊天室_第2张图片
3.客户端5127.0.0.1:55422控制台输出

netty实现简易聊天室_第3张图片

以上就是聊天室的基本内容了,第一次写博客,略显生疏,往后继续更新所学技术知识

你可能感兴趣的:(java,开发语言)