[开源] 即时通讯组件---ImCore

前言

ImCore 是一款 .NETCore 下利用 WebSocket 实现的简易、高性能、集群即时通讯组件,支持点对点通讯、群聊通讯、上线下线事件消息等众多实用性功能。

开源地址:https://github.com/2881099/im ,求 star~~

快速开始

dotnet add package ImCore

IM服务端

public void Configure(IApplicationBuilder app)
{
    app.UseImServer(new ImServerOptions
    {
        Redis = new CSRedis.CSRedisClient("127.0.0.1:6379,poolsize=5"),
        Servers = new[] { "127.0.0.1:6001" }, //集群配置
        Server = "127.0.0.1:6001"
    });
}

一套永远不需要迭代更新的IM服务端

WebApi业务端

public void Configure(IApplicationBuilder app)
{
    //...

    ImHelper.Initialization(new ImClientOptions
    {
        Redis = new CSRedis.CSRedisClient("127.0.0.1:6379,poolsize=5"),
        Servers = new[] { "127.0.0.1:6001" }
    });

    ImHelper.EventBus(
        t => Console.WriteLine(t.clientId + "上线了"), 
        t => Console.WriteLine(t.clientId + "下线了"));
}

ImHelper方法

参数

描述

PrevConnectServer

(clientId, string)

在终端准备连接 WebSocket 前调用

SendMessage

(发送者, 接收者, 消息内容, 是否回执)

发送消息

GetClientListByOnline

-

返回所有在线clientId

EventBus

(上线委托, 离线委托)

socket上线与下线事件

群聊频道

参数

描述

JoinChan

(clientId, 频道名)

加入

LeaveChan

(clientId, 频道名)

离开

GetChanClientList

(频道名)

获取群聊频道所有clientId

GetChanList

-

获取所有群聊频道和在线人数

GetChanListByClientId

(clientId)

获取用户参与的所有群聊频道

GetChanOnline

(频道名)

获取群聊频道的在线人数

SendChanMessage

(clientId, 频道名, 消息内容)

发送群聊消息,所有在线的用户将收到消息

说明:clientId 应该与 webApi的用户id相同,或者有关联。

Html5终端

本方案支持集群分区,前端连接 websocket 前,应该先请求 webApi 获得地址(ImHelper.PrevConnectServer)。

运行示例

运行环境:.NETCore 2.1 + redis-server 2.8 下载Redis-x64-2.8.2402.zip,点击 start.bat 运行; cd imServer && dotnet run cd web && dotnet run 打开多个浏览器,访问 http://127.0.0.1:5000 发送群消息

设计思路

imServer 是 websocket 服务中心,可部署多实例,按clientId分区管理socket连接;

webApi 或其他应用端,使用 ImHelper 调用相关方法(如:SendMessage、群聊相关方法);

消息发送利用了 redis 订阅发布技术。每个 imServer 订阅相应的频道,收到消息,指派 websocket 向终端(如浏览器)发送消息;

1、可缓解并发推送消息过多的问题;

2、可解决连接数过多的问题;

客户端连接流程:client -> websocket -> imserver

imserver 订阅消息:client <- imserver <- redis channel

推送消息流程:web1 -> sendmsg方法 -> redis channel -> imserver

imserver 充当消息转发,及维护连接中心,代码万年不变不需要重启维护;

WebSocket

比较笨的办法是浏览器端使用websocket,其他端socket,这种混乱的设计非常难维护。

强烈建议所有端都使用websocket协议,adorid/ios/h5/小程序全部支持websocket客户端。

业务与通讯协议

im系统一般涉及【我的好友】、【我的群】、【历史消息】等等。。

那么,imServer与业务方(webApi)该保持何种关系呢?

用户A向好友B发送消息,分析一下:

  • 需要判断B是否为A好友;
  • 需要判断A是否有权限;
  • 等等。。

诸如此类业务判断会很复杂,我们试想一下,如果使用imServer做业务协议,它是不是会变成巨无霸难以维护?

又比如获取历史聊天记录,难道客户端要先websocket.send('gethistory'),再在onmessage里定位回调处理?


我们可以这样设定,所有用户的主动行为走业务方(webApi),imServer只负责即时消息推送。什么意思?

用户A向好友B发送消息:客户端请求业务方(webApi)接口,由业务方(webApi)后端向imServer发起推送请求,imServer收到指令后,向前端用户B的websocket发送数据,用户B收到了消息。

获取历史消息:客户端请求业务方(webApi)接口,返回json(历史消息)

回执:用户A如何知道消息发送状态(成功或失败或不在线)?imServer端向用户B发送消息时,把状态以消息的方式推给用户A即可(按上面的逻辑),具体请看源码吧。。。

发送消息

采用 redis 轻量级的订阅发布功能,实现消息缓冲发送。

集群分区

单个imServer实例支持多少个客户端连接,两千个没问题?

如果在线用户有10万人,怎么办???

比如部署4个imServer:

imServer1 订阅 redisChanne1 imServer2 订阅 redisChanne2 imServer3 订阅 redisChanne3 imServer4 订阅 redisChanne4

业务方(webApi)端根据接收方的clientId后四位16进制与节点总数取模,定位到对应的redisChannel,进行redis->publish操作将消息定位到相应的imServer。

每个 imServer 管理着对应的终端连接,当接收到 redis 订阅消息后,向对应的终端连接推送数据。

事件消息

IM 系统比较常用的有上线、下线,在 imServer 层才能准确捕捉事件,但业务代码就不合适在这上面编写了。

采用 redis 发布订阅技术,将上线、下线等事件向指定频道发布,业务方(webApi) 通过 ImHelper.EventBus 方法进行订阅捕捉。

结束语

谢谢支持!

本文分享自微信公众号 - DotNet程序园(dotnetblog)

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2019-07-31

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏VB小源码

VB.NET 直接读取打开的Excel数据到DataGridView

Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.Even...

48120
来自专栏Eureka伽罗的技术时光轴

完成端口(CompletionPort)详解 - 手把手教你玩转网络编程系列之三

----- By PiggyXP(小猪...

17180
来自专栏架构师

c#基础系列1---值类型和引用类型

不知不觉已经踏入坑已10余年之多,对于c#多多少少有一点自己的认识,写出来渴求同类抨击,对自己也算是个十年之痒的一个总结。

8210
来自专栏Eureka伽罗的技术时光轴

win10中“windbg+vmware+win7双机调试”设置

本文主要介绍在win10下如何设置windbg+vmware,以进行双机调试。本文主要参考:李Sir的博客,并浏览了大量网文,以及windbg自带的help文档...

13440
来自专栏架构师

C# 8中的Async Streams

C# 5引入了Async/Await,用以提高用户界面响应能力和对Web资源的访问能力。换句话说,异步方法用于执行不阻塞线程并返回一个标量结果的异步操作。

10020
来自专栏架构师

c#基础系列2---深入理解 String

string(严格来说应该是System.String) 类型是我们日常coding中用的最多的类型之一。那什么是String呢?^ ~ ^

8120
来自专栏信息安全小学生

C++ 和 Makefile 笔记

比如工程目录下,将CPP文件放置在 src 目录下,H文件放在 header下,则makefile可以这样写

18130
来自专栏VB小源码

VB.net datagridview转Excel,datatable转数组

VB.net datagridview转Excel,datatable转数组,简单说就是通过datatable转换成二维数组,然后导出数据到Excel文件,可以...

20520
来自专栏依乐祝

荐读|属性与可直接访问的数据成员之间应该如何选

在书写C#代码的时候你是否有过这样的经历:经常混用属性以及公有的数据成员。毕竟他们的用法基本一致,对于使用来说好像没什么区别啊。其实我也经常使用类的公有的数据成...

8830
来自专栏架构师

c#基础系列3---深入理解ref 和out

在上篇文章深入理解值类型和引用类型的时候,有的小伙伴就推荐说一说ref和out 关键字,昨天晚上彻夜难眠在想是否要谈一下呢,因为可谈的不是太多,也可能是我理解的...

6710

扫码关注云+社区

领取腾讯云代金券

年度创作总结 领取年终奖励