手写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和端口 发送内容即可实现群聊
早年同窗始相知,三载瞬逝情却萌。年少不知愁滋味,犹读红豆生南国。别离方知相思苦,心田红豆根以生。