美文网首页
IM即时通讯开发在Netty基础上编码实践群聊功能

IM即时通讯开发在Netty基础上编码实践群聊功能

作者: 可爱的小云朵 | 来源:发表于2023-03-20 14:03 被阅读0次

群聊的大概流程就是:根据群组 ID 查找到所有的成员集合,然后再遍历找到每个成员对应的连接通道。

群聊通讯流程技术原理如下:

1)群聊和单聊整体上的思路一致:需要保存每个用户和通道的对应关系,方便后期通过用户 ID 去查找到对应的通道,再跟进通道推送消息;2)群聊把消息发送给群员的原理:其实很简单,服务端再保存另外一份映射关系,那就是聊天室和成员的映射关系。发送消息时,首先根据聊天室 ID 找到对应的所有成员,然后再跟进各个成员的 ID 去查找到对应的通道,最后由每个通道进行消息的发送;3)群成员加入某个群聊聊的时候:往映射表新增一条记录,如果成员退群的时候则删除对应的映射记录。

服务端实体

服务端映射关系的管理,分别是:

1)登录信息(用户 ID 和通道);2)群组信息(群组 ID 和群组成员关系)。

主要通过两个 Map 去维护,具体如下:

public class ServerChatGroupHandler extends ChannelInboundHandlerAdapter {

private static Map map=new HashMap();

private static Map groups=new HashMap();

}

//组和成员列表关系实体

@Data

public class Group implements Serializable {

private String groupName;

private List members=new ArrayList();

}

//成员和连接通道的关系实体

public class GroupMember implements Serializable {

private Integer userid;

private Channel channel;

}

我们准备好相应的实体,以及实体和指令的映射关系,具体如下所示:

private static Map> map=new HashMap>();

static{

//登录的请求和响应实体

map.put(1, LoginReqBean.class);

map.put(2, LoginResBean.class);

//创建群组的请求和响应实体

map.put(3, GroupCreateReqBean.class);

map.put(4, GroupCreateResBean.class);

//查看群组的请求和响应实体

map.put(5, GroupListReqBean.class);

map.put(6, GroupListResBean.class);

//加入群组的请求和响应实体

map.put(7,GroupAddReqBean.class);

map.put(8,GroupAddResBean.class);

//退出群组的请求和响应实体

map.put(9,GroupQuitReqBean.class);

map.put(10,GroupQuitResBean.class);

//查看成员列表的请求和响应实体

map.put(11,GroupMemberReqBean.class);

map.put(12,GroupMemberResBean.class);

//发送响应的实体(发送消息、发送响应、接受消息)

map.put(13,GroupSendMsgReqBean.class);

map.put(14,GroupSendMsgResBean.class);

map.put(15,GroupRecMsgBean.class);

}

IM群聊功能的实现,我们需要两个两个业务 Handler:

1)分别是客户端(ClientChatGroupHandler);2)服务端(ServerChatGroupHandler)。

客户端 Handler

客户端 Handler,主要是通过判断实体类型来做不同的业务操作,当然也可以使用 SimpleChannelInboundHandler 去进行 Handler 拆分。

public class ClientChatGroupHandler extends ChannelInboundHandlerAdapter {

@Override

public void channelActive(ChannelHandlerContext ctx) throws Exception {

//在链接就绪时登录

login(ctx.channel());

}

//主要是“接受服务端”的响应信息

@Override

public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {

if(msg instanceof LoginResBean){

LoginResBean res=(LoginResBean) msg;

System.out.println("登录响应:"+res.getMsg());

if(res.getStatus()==0){

//登录成功

//1.给通道绑定身份

ctx.channel().attr(AttributeKey.valueOf("userid")).set(res.getUserid());

//2.显示操作类型【请看下面】

deal(ctx.channel());

}else{

//登录失败,继续登录

login(ctx.channel());

}

}else if(msg instanceof GroupCreateResBean){

GroupCreateResBean res=(GroupCreateResBean)msg;

System.out.println("创建响应群组:"+res.getMsg());

}else if(msg instanceofGroupListResBean){

GroupListResBean res=(GroupListResBean)msg;

System.out.println("查看群组列表:"+res.getLists());

}elseif(msg instanceofGroupAddResBean){

GroupAddResBean res=(GroupAddResBean)msg;

System.out.println("加入群组响应:"+res.getMsg());

}elseif(msg instanceof GroupQuitResBean){

GroupQuitResBean res=(GroupQuitResBean)msg;

System.out.println("退群群组响应:"+res.getMsg());

}else if(msg instanceof GroupMemberResBean){

GroupMemberResBean res=(GroupMemberResBean)msg;

if(res.getCode()==1){

System.out.println("查看成员列表:"+res.getMsg());

}else{

System.out.println("查看成员列表:"+res.getLists());

}

}else if(msg instanceof GroupSendMsgResBean){

GroupSendMsgResBean res=(GroupSendMsgResBean)msg;

System.out.println("群发消息响应:"+res.getMsg());

}else if(msg instanceof GroupRecMsgBean){

GroupRecMsgBean res=(GroupRecMsgBean)msg;

System.out.println("收到消息fromuserid="+

res.getFromuserid()+

",msg="+res.getMsg());

}

}

}

通过子线程循环向输出控制台输出操作类型的方法,以下方法目前都是空方法,下面将详细讲解。即时通讯开发可以咨询小蓝豆

private void deal(final Channel channel){

final Scanner scanner=new Scanner(http://System.in);

new Thread(new Runnable() {

public void run() {

while(true){

System.out.println("请选择类型:0创建群组,1查看群组,2加入群组,3退出群组,4查看群成员,5群发消息");

int type=scanner.nextInt();

switch(type){

case 0:

createGroup(scanner,channel);

break;

case 1:

listGroup(scanner,channel);

break;

case 2:

addGroup(scanner,channel);

break;

case 3:

quitGroup(scanner,channel);

break;

case 4:

listMembers(scanner,channel);

break;

case 5:

sendMsgToGroup(scanner,channel);

break;

default:

System.out.println("输入的类型不存在!");

}

}

}

}).start();

}

相关文章

  • Netty实战:设计一个IM框架

    bitchat bitchat 是一个基于 Netty 的 IM 即时通讯框架 项目地址:https://gith...

  • Netty实战:设计一个IM框架

    bitchat bitchat 是一个基于 Netty 的 IM 即时通讯框架 项目地址:https://gith...

  • Netty 编码解码

    参考来源 Netty实践 Netty 4.x学习笔记 - Channel和Pipeline Netty 编码器和解...

  • Netty实战:设计一个IM框架就这么简单!

    bitchat 是一个基于 Netty 的 IM 即时通讯框架 项目地址:https://github.com/a...

  • Netty简单案例

    一本非常不错的小册:Netty 入门与实战:仿写微信 IM 即时通讯系统 Netty是一个异步事件驱动的网络应用框...

  • 2018-08-29

    产投集团APP-智慧党建系统IM群聊模块设置1、新增退出群聊功能2、新增删除群成员功能

  • 阿里百川即时通讯IM集成

    最近项目中用到了即时通讯,需要使用单聊 群聊等功能,经过一番对比,最终选择了阿里系的阿里百川IM,选择阿里的原因主...

  • Android 即时通讯开发小结(二)

    《Android 即时通讯开发小结》基于IM Andriod 开发的各种常见问题,结合网易云信即时通讯技术的实践,...

  • Android 即时通讯开发小结(一)

    《Android 即时通讯开发小结》基于IM Andriod 开发的各种常见问题,结合网易云信即时通讯技术的实践,...

  • Netty学习笔记(三)

    Netty 应用实例:群聊系统。 要求:①实现多人群聊;②服务器端:可以监测用户上线,离线,并实现消息转发功能;③...

网友评论

      本文标题:IM即时通讯开发在Netty基础上编码实践群聊功能

      本文链接:https://www.haomeiwen.com/subject/ziwurdtx.html