群聊消息的收发及 Netty 性能优化
通过前面小节的学习,相信大家看到本小节标题就已经知道该如何实现本小节的功能了吧,为了给大家学到更多的知识,在实现了群聊消息收发之后,本小节将带给大家更多的惊喜。
开始实现之前,我们还是先来看一下群聊的最终效果。
1. 群聊消息最终效果
服务端
闪电侠,逆闪,极速先后登录,然后闪电侠拉逆闪,极速和自己加入群聊,下面,我们来看一下各位客户端的控制台界面
客户端 - 闪电侠
闪电侠第一个输入 "sendToGroup" 发送群消息。
客户端 - 逆闪
逆闪第二个输入 "sendToGroup" 发送群消息,在前面已经收到了闪电侠的消息。
客户端 - 极速
逆闪最后一个输入 "sendToGroup" 发送消息,在前面已经收到了闪电侠和逆闪的消息。
- 在闪电侠的控制台,输入 "sendToGroup" 指令之后,再输入 groupId + 空格 + 消息内容,发送消息给群里各位用户,随后,群组里的所有用户的控制台都显示了群消息。
- 随后,陆续在逆闪和极速的控制台做做相同的操作,群组里的所有用户的控制台陆续展示了群消息。
这个实现过程和我们前面的套路一样,下面我们仅关注核心实现部分。
2. 群聊消息的收发的实现
核心实现部分其实就是服务端处理群消息的 handler - GroupMessageRequestHandler
GroupMessageRequestHandler.java
public class GroupMessageRequestHandler extends SimpleChannelInboundHandler<GroupMessageRequestPacket> {
@Override
protected void channelRead0(ChannelHandlerContext ctx, GroupMessageRequestPacket requestPacket) {
// 1.拿到 groupId 构造群聊消息的响应
String groupId = requestPacket.getToGroupId();
GroupMessageResponsePacket responsePacket = new GroupMessageResponsePacket();
responsePacket.setFromGroupId(groupId);
responsePacket.setMessage(requestPacket.getMessage());
responsePacket.setFromUser(SessionUtil.getSession(ctx.channel()));
// 2. 拿到群聊对应的 channelGroup,写到每个客户端
ChannelGroup channelGroup = SessionUtil.getChannelGroup(groupId);
channelGroup.writeAndFlush(responsePacket);
}
}
- 首先,通过 groupId 构造群聊响应
GroupMessageResponsePacket
,然后再把发送群聊的用户信息填入,这里的用户信息我们就直接复用与 channel 绑定的 session了。 - 然后,我们拿到对应群组的
ChannelGroup
,通过writeAndFlush()
写到客户端。
完整代码大家可以参考 github 对应本小节分支,下面进入我们本小节的几个重要知识点,可以拿小本本开始记了。
3. 共享 handler
在使用 Netty 完成了一个 IM 系统的核心功能之后,我们再来仔细看一下服务端
NettyServer.java
serverBootstrap
.childHandler(new ChannelInitializer<NioSocketChannel>() {
protected void initChannel(NioSocketChannel ch) {
ch.pipeline().addLast(new Spliter());
ch.pipeline().addLast(new PacketDecoder());
ch.pipeline().addLast(new LoginRequestHandler());
ch.pipeline().addLast(new AuthHandler());
ch.pipeline().addLast(new MessageRequestHandler());
ch.pipeline().addLast(ne