手写IM群聊基于netty

如下代码 编写群聊的server端 本文主要体会思想,

好友列表,分组关系以及聊天记录等都可以基于业务去数据库维护

package com.shanhe.register;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.string.StringDecoder;
import io.netty.handler.codec.string.StringEncoder;
import io.netty.handler.timeout.IdleStateHandler;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;


public class GroupChatServer {
    public static void main(String[] args) throws InterruptedException {
        EventLoopGroup bossGroup = new NioEventLoopGroup();
        EventLoopGroup workerGroup = new NioEventLoopGroup();
        ServerBootstrap bootstrap = new ServerBootstrap()
                .group(bossGroup, workerGroup)
                .channel(NioServerSocketChannel.class)
                .childHandler(new ChannelInitializer<SocketChannel>() {
                    @Override
                    protected void initChannel(SocketChannel ch) {
                        ChannelPipeline pipeline = ch.pipeline();
                        pipeline.addLast(new StringEncoder());
                        pipeline.addLast(new StringDecoder());
                        pipeline.addLast(new IdleStateHandler(3, 0, 0));
                        pipeline.addLast(new GroupChat());
                    }
                });
        ChannelFuture future = bootstrap.bind(8999).sync();
        System.out.println("群聊天系统启动成功...");
        future.channel().closeFuture().sync();
    }

    static class GroupChat extends SimpleChannelInboundHandler<String> {
        // 保存客户端连接或者用ConcurrentHashMap来存放 
        private static List<ChannelHandlerContext> ctxs = new ArrayList<>();
        private static SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

        /**
         * 读取数据
         *
         * @param ctx
         * @param msg
         * @throws Exception
         */
        @Override
        protected void channelRead0(ChannelHandlerContext ctx, String msg) throws Exception {
            Channel channel = ctx.channel();
            massHair(dateFormat.format(new Date()) + "【客户端】" + channel.remoteAddress() + msg, ctx);
        }

        /**
         * 刚建立活跃连接 上线
         *
         * @param ctx
         * @throws Exception
         */
        @Override
        public void channelActive(ChannelHandlerContext ctx) throws Exception {
            Channel channel = ctx.channel();
            massHair(dateFormat.format(new Date()) + "【客户端】" + channel.remoteAddress() + ",已经上线啦!", ctx);
            // 保存连接
            ctxs.add(ctx);
        }

        /**
         * 客户端主动断开连接 可以实现断开
         *
         * @param ctx
         * @throws Exception
         */
        @Override
        public void channelInactive(ChannelHandlerContext ctx) throws Exception {
            Channel channel = ctx.channel();
//            massHair(dateFormat.format(new Date()) + "【客户端】" + channel.remoteAddress() + ",已经退出群聊系统");
            massHair(dateFormat.format(new Date()) + "【客户端】" + channel.remoteAddress() + ",已经退出群聊系统", ctx);
            ctxs.remove(ctx);
        }

        /**
         * 群发
         *
         * @param str
         */
        private void massHair(String str, ChannelHandlerContext ctx) {
            ctxs.forEach((t) -> {
                if (t != ctx) {
                    t.writeAndFlush(str);
                }
            });
        }
    }

}

接着写一个client连接或者使用NetAssist网络助手客户端 多开几个连接上ip和端口 发送内容即可实现群聊

 

posted @ 2023-02-06 17:33  山河永慕~  阅读(43)  评论(0编辑  收藏  举报