本篇涉及的群聊核心功能,大致如下所示:
- 1)登录:每个客户端连接服务端的时候,都需要输入自己的账号信息,以便和连接通道进行绑定;
- 2)创建群组:输入群组 ID 和群组名称进行创建群组。需要先根据群组 ID 进行校验,判断是否已经存在了;
- 3)查看群组:查看目前已经创建的群组列表;
- 4)加入群组:主要参数是群组 ID 和用户 ID,用户 ID 只需从 Channel 的绑定属性里面获取即。主要是判断群组 ID 是否存在,如果存在还需要判断该用户 ID 是否已经在群组里面了;
- 5)退出群组:主要是判断群组 ID 是否存在,如果存在则删除相应的关系;
- 6)查看组成员:根据群组 ID 去查询对应的成员列表;
- 7)群发消息:选择某个群进行消息发送,该群下的成员都能收到信息。主要判断群组 ID 是否存在,如果存在再去获取其对应的成员列表。
群聊原理
其实群聊和单聊,整体上原理是一样的,只是做了一下细节上的升级。
在首篇《IM系统设计篇》的“6、IM群聊思路设计”设计部分也做了详细的说明了。
群聊的大概流程就是:根据群组 ID 查找到所有的成员集合,然后再遍历找到每个成员对应的连接通道。
群聊通讯流程技术原理如下:
- 1)群聊和单聊整体上的思路一致:需要保存每个用户和通道的对应关系,方便后期通过用户 ID 去查找到对应的通道,再跟进通道推送消息;
- 2)群聊把消息发送给群员的原理:其实很简单,服务端再保存另外一份映射关系,那就是聊天室和成员的映射关系。发送消息时,首先根据聊天室 ID 找到对应的所有成员,然后再跟进各个成员的 ID 去查找到对应的通道,最后由每个通道进行消息的发送;
- 3)群成员加入某个群聊聊的时候:往映射表新增一条记录,如果成员退群的时候则删除对应的映射记录。
运行效果
补充说明:因为本系列文章主要目的是引导IM初学者在基于Netty的情况下,如何一步一步从零写出IM的逻辑和思维能力,因而为了简化编码实现,本篇中编码实现的客户端都是基于控制台实现的(希望不要被嫌弃),因为理解技术的本质显然比炫酷的外在表现形式更为重要。即时通讯聊天软件app开发可以加小蓝豆的v:weikeyun24咨询
服务端映射关系的管理,分别是:
- 1)登录信息(用户 ID 和通道);
- 2)群组信息(群组 ID 和群组成员关系)。
主要通过两个 Map 去维护,具体如下:
public class ServerChatGroupHandler extends ChannelInboundHandlerAdapter {
private static Map<Integer, Channel> map=new HashMap<Integer, Channel>();
private static Map<Integer, Group> groups=new HashMap<Integer, Group>();
}
//组和成员列表关系实体
@Data
public class Group implements Serializable {
private String groupName;
private List<GroupMember> members=new ArrayList<GroupMember>();
}
//成员和连接通道的关系实体
public class GroupMember implements Serializable {
private Integer userid;
private Channel channel;
}
IM群聊功能的实现,我们需要两个两个业务 Handler:
- 1)分别是客户端(ClientChatGroupHandler);
- 2)服务端(ServerChatGroupHandler)。
客户端 Handler
客户端 Handler,主要是通过判断实体类型来做不同的业务操作,当然也可以使用 SimpleChannelInboundHandler 去进行 Handler 拆分。