[开源] .NETCore websocket 即时通讯组件---ImCore
ImCore 利用 webSocket 协议实现简易、高性能、集群即时通讯组件,支持点对点通讯、群聊通讯、上线下线事件消息等众多实用性功能。
Quick Start
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),伪代码:
ajax('/prev-connect-imserver', function(data) {
var url = data; //此时的值:ws://127.0.0.1:6001/ws?token=xxxxx
var sock = new WebSocket(url);
sock.onmessage = function (e) {
//...
};
})
Demo
运行环境:.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 发送群消息

设计思路
终端(如浏览器) 使用 webSocket 连接 imServer;
imServer 根据 clientId 分区管理 webSocket 连接,可群集部署;
webApi 或其他应用端,使用 ImHelper 调用相关方法(如:SendMessage、群聊相关方法),将数据推至 Redis Channel;
imServer 订阅 Redis Channel,收到消息后向终端(如浏览器)推送消息;
1、可缓解并发推送消息过多的问题;
2、可解决连接数过多的问题;
3、解决业务和通讯分离,结构更加清淅;
imServer 充当消息转发,维护连接,代码万年不变不需要重启维护
webApi 负责所有业务
webSocket
如果浏览器使用 webSocket ,iOS 使用其他协议,协议不一致的后果很严重(难维护)。
建议所有端都使用 webSocket 协议,adorid/ios/h5/小程序 全部支持 webSocket 客户端。
业务通讯
IM 系统一般涉及【我的好友】、【我的群】、【历史消息】等等。。
那么,imServer与业务方(webApi)该保持何种关系呢?
用户A向好友B发送消息,分析一下:
- 需要判断B是否为A好友;
- 需要判断A是否有权限;
- 等等。。
诸如此类业务判断会很复杂,如果使用imServer做业务协议,它是不是会变成巨无霸难以维护?
又如获取历史聊天记录,难道客户端要先webSocket.send('gethistory'),再在onmessage里定位回调处理?
发送消息
业务和推送分离的设计,即 imServer 只负责推送工作,webApi 负责业务。
用户A向B发消息:终端A ajax -> webApi -> imServer -> 终端B webSocket.onmessage;
获取历史消息:客户端请求业务方(webApi)接口,返回json(历史消息)。
背后采用 redis 轻量级的订阅发布功能,实现消息缓冲发送,方案必备之一,后期可更换为其他技术。比如 webApi 业务发需要通知1000个人,若不用消息缓冲,会对 webApi 应用程序整体将造成性能损耗。
还有使用 redis 存储一些数据,如在线 clientId,频道信息。
集群分区
单个 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 方法进行订阅捕捉。

A向B发文件的例子
1、A向 webapi 传文件
2、webapi 告诉 imServer,A向B正在传文件,ImHelper.SendMessage(B, "A正在给传送文件...")
3、B收到消息,A正在传文件
4、webapi 文件接收完成时告诉imServer,A向B文件传输完毕,ImHelper.SendMessage(B, "A文件传输完毕(含文件链接)")
5、B收到消息,A文件传输完毕(含文件链接)
有感而发
为什么说 signalr 不合适做 im?
im 的特点必定是长连接,轮训的功能用不上。
因为他是双工通讯的设计,用 hub.invoke 发送命令给服务端处理业务,其他就和 ajax 差不多,用来代替 ajax 减少 http 请求数量比较看好。
但是过多使用 hub,signalr 服务端会被业务入侵严重,业务变化频繁后不得不重新发布版本,每次部署所有终端都会断开连接,遇到5分钟发一次业务补丁的时候,类似离线和上线提示好友的功能就无法实现。
ImCore 的设计是业务和推送分离,即 imServer 永不更新重启,业务全部在 webApi 上编写,终端连接的是 imServer 就不会频繁重启的问题。
[开源] .NETCore websocket 即时通讯组件---ImCore的更多相关文章
- [重磅开源] 比SingleR更适合的websocket 即时通讯组件---ImCore开源了
有感而发 为什么说 SignalR 不合适做 IM? IM 的特点必定是长连接,轮训的功能用不上. 因为它是双工通讯的设计,用hub.invoke发送命令给服务端处理业务,其他就和 ajax 差不多, ...
- NetCore WebSocket 即时通讯示例
1.新建Netcore Web项目 2.创建简易通讯协议 public class MsgTemplate { public string SenderID { get; set; } public ...
- java SSM框架 代码生成器 快速开发平台 websocket即时通讯 shiro redis
A代码编辑器,在线模版编辑,仿开发工具编辑器,pdf在线预览,文件转换编码 B 集成代码生成器 [正反双向](单表.主表.明细表.树形表,快速开发利器)+快速表单构建器 freemaker模版技术 , ...
- Springboot 项目源码 Activiti6 工作流 vue.js html 跨域 前后分离 websocket即时通讯
特别注意: Springboot 工作流 前后分离 + 跨域 版本 (权限控制到菜单和按钮) 后台框架:springboot2.1.2+ activiti6.0.0+ mybaits+maven+接 ...
- 使用tomcat方式实现websocket即时通讯服务端讲解
使用tomcat方式实现websocket即时通讯服务端讲解 第一种方案:使用Tomcat的方式实现 tomcat版本要求:tomcat7.0+.需要支持Javaee7 导入javeee-api的ja ...
- java ssm 后台框架平台 项目源码 websocket 即时通讯 IM quartz springmvc
官网 http://www.fhadmin.org/D 集成安全权限框架shiro Shiro 是一个用 Java 语言实现的框架,通过一个简单易用的 API 提供身份验证和授权,更安全,更可靠E ...
- java SSM 框架 代码生成器 websocket即时通讯 shiro redis
1. 权限管理:点开二级菜单进入三级菜单显示 角色(基础权限)和按钮权限 角色(基础权限): 分角色组和角色,独立分配菜单权限和增删改查权限. 按钮权限: 给角色分配按钮权限. ...
- 一款Java开源的Springboot即时通讯 IM,附源码
# 开篇 电商平台最不能缺的就是即时通讯,例如通知类下发,客服聊天等.今天,就来给大家分享一个开源的即时通讯系统.如对文章不感兴趣可直接跳至文章末尾,有获取源码链接的方法. 但文章内容是需要你简单的过 ...
- 个人开源作品,即时通讯App支持文本、语音、图片聊天
开源一个即时通讯类App,支持纯文本.语音.地理位置.图片聊天,同时还加入了好友圈功能,支持分享动态和发送图片,支持搜索附近的人,使用的百度地图定位功能:由Bmob后端云提供服务器支持,欢迎喜欢的伙伴 ...
随机推荐
- C++按格式接收输入字符(京东,滴滴,360笔试必用)
头一次起这种标题,为了对得起这个标题,我尽量多写点~ 最近还是一边实习一遍投简历--笔试--面试,然而发现了自己的好多问题. 在答了京东笔试(滴滴,360也是这样的)的题后,发现与腾讯,阿里等公司的不 ...
- C# 简单TCP协议
namespace TCPServer { class Program { static void Main(string[] args) { ;//端口 TcpClient tcpClient;// ...
- net开发框架never
[一] 摘要 never是纯c#语言开发的一个框架,同时可在netcore下运行. 该框架github地址:https://github.com/shelldudu/never 同时,配合never_ ...
- Salesforce LWC学习(二) helloWorld程序在VSCode中的实现
上一篇我们简单的描述了一下Salesforce DX的配置以及CLI的简单功能使用,此篇主要简单描述一下LWC如何实现helloWorld以及LWC开发时应该注意的一些规范. 做国内项目的同学直观的感 ...
- Mac上使用ssh连接服务器title显示服务器的ip
Mac上使用ssh连接服务器title显示服务器的ip 使用Mac开发时,管理的服务器过多时,会搞混乱.可能有时啪啪啪一顿操作,最后发现操作错了机器. 解决方案 在远程服务器上,编辑vim /etc/ ...
- python 基础学习笔记(3)--列表与元组
**本次笔记主要内容为 列表,元组主要的功能和特性** **1.列表**: 学习过c语言的同学应该知道,c语言有数组这一功能,就是将数据类型相同的元素放在一起.由于python的变量没有数据类型,也就 ...
- linuxprobe培训第1节课笔记2019年7月5日
报了老刘的RHCE培训,这是老刘上课笔记简略版. 老刘在课上介绍了开源共享精神和大胡子(Richard M. Stallman—GNU创始人).linux发展史(Linus Benedict Torv ...
- 环形缓存RingBuf的几种实现方式(数组,链表),及Disruptor的分析
先贴个头文件的设计: 首先缓冲区中没有任何数据时,nIdWrite.nIdRead读写下标都为0. 为了判断缓冲区中是否还有数据可读或者可写,我判断的依据是:1)当nIdWrite 等于 nIdRea ...
- 灵雀云CTO陈恺应邀出席国泰君安信息产业投资峰会,探讨全球科技产业新格局
2019年7月9-10日,国泰君安信息产业投资峰会在上海陆家嘴举办.作为国内容器PaaS领域的龙头公司,灵雀云受邀出席本次大会,在“数字化转型从云做起”的论坛中,CTO陈恺发表了<云原生助力企业 ...
- Logstash : 从 SQL Server 读取数据
有些既存的项目把一部分日志信息写入到数据库中了,或者是由于其它的原因我们希望把关系型数据库中的信息读取到 elasticsearch 中.这种情况可以使用 logstash 的 jdbc input ...