ASP.NET SingalR 点对点聊天实现思路总结
前一段时间写了一个简单的聊天室,是群聊的方式。博客地址:http://www.cnblogs.com/panzi/p/4980346.html。还有一种需求就是常见的尤其是培训机构的主页面,经常会有1对1咨询聊天窗口。那么用singalR如何实现1对1聊天呢。
其实很简单。我们先看看SingalR里的IHubConnectionContext接口代码:
public interface IHubConnectionContext<T>
{
//所有连接服务器的用户
T All { get; }
//除了一部分用户
T AllExcept(params string[] excludeConnectionIds);
//这个就是我们要用的点对点,针对单个用户发送消息
T Client(string connectionId);
//群发消息
T Clients(IList<string> connectionIds);
//按组群发消息
T Group(string groupName, params string[] excludeConnectionIds);
//多组群发消息
T Groups(IList<string> groupNames, params string[] excludeConnectionIds);
//用户
T User(string userId);
T Users(IList<string> userIds);
}
这里我们就用 T Client(string connectionId); 这个方法。调用方式为 Clients.Client("connectionId").clientFun(msg); //(clientFun为自定义客户端接收消息方法名)具体细节不在描述,这里比较关键的就是,如何知道对方的ConnectionId,因为ConnectionId是自动生成的而且,每次刷新页面都会变,SingalR本身又不带统计在线用户的方法,所以,这个需要自己去实现。思路很清晰,这里先用 静态List做用户在线列表信息存储。代码如下:
/// <summary>
/// 简单用户统计model
/// </summary>
public class HubUser
{
/// <summary>
/// 连接服务器之后,自动生成的connectionId
/// </summary>
public string ConnectionId { get; set; }
/// <summary>
/// 客户端用户的主键ID
/// 一般和业务相关的用户ID
/// </summary>
public string ClientUserId { get; set; }
/// <summary>
/// 聊天所在组
/// </summary>
public string GroupId { get; set; }
}
public sealed class OnlineUserPool
{
private static Lazy<List<HubUser>> _onlineUser = new Lazy<List<HubUser>>();
public static List<HubUser> OnlineUser { get { return _onlineUser.Value; } } /// <summary>
/// 添加用户,一般在用户 连接服务器或者用户重新连接的时候
/// </summary>
/// <param name="user"></param>
public static void AddUser(HubUser user)
{
DeleteUser(user);
_onlineUser.Value.Add(user);
}
/// <summary>
/// 删除某个在线用户
/// </summary>
/// <param name="clientUserId"></param>
/// <param name="connectionId"></param>
public static void DeleteUser(HubUser user, bool unConnected = true)
{
var onlineUser = IsOnline(user);
if (onlineUser != null)
{
_onlineUser.Value.Remove(onlineUser);
}
}
public static HubUser IsOnline(HubUser user)
{
if (user == null) { throw new ArgumentNullException(); }
string clientUserId = user.ClientUserId;
string connectionId = user.ConnectionId;
if (!string.IsNullOrEmpty(clientUserId))
{
return _onlineUser.Value.FirstOrDefault(x => x.ClientUserId == clientUserId);
}
else
{
return _onlineUser.Value.FirstOrDefault(x => x.ConnectionId == connectionId);
}
}
/// <summary>
/// 获取在线总数
/// </summary>
/// <returns></returns>
public static long GetUserCount()
{
return _onlineUser.Value.Count;
}
}
可以看到 OnlineUserPool 类实现了往静态列表添加用户,删除用户等一系列操作。
添加用户操作需要,在用户接入到聊天室的时候执行:
public Task Join(ZjMessage message)
{
message.connectionId = Context.ConnectionId;
//就是用户加入的时候
OnlineUserPool.AddUser(new HubUser
{
ClientUserId = message.userid,
ConnectionId = Context.ConnectionId
});
message.msg = "当前已经有:" + OnlineUserPool.GetUserCount() + " 人在线";
return Clients.All.receiveMessage(new { type = "join", msg = message });
}
删除用户操作就在重写OnDisconnect方法里执行,需要根据ConnectionId删除
public override Task OnDisconnected(bool stopCalled)
{
ZjMessage message = new ZjMessage(Context.ConnectionId);
//用户离开
//用户断线,需要将该用户从列表中删除,(应该考虑短暂失去连接的可能性,不能直接从列表删除。)
OnlineUserPool.DeleteUser(new HubUser
{
ConnectionId = Context.ConnectionId
});
return Clients.All.receiveMessage(new { type = "left", msg = message });
}
所以,当你想点对点发送消息的时候,将对方userId传送到服务器,然后服务器从在线列表里面查询出相应的connectionID,然后将消息推送到该connectionID的用户,就实现了在线两个人聊天了。当然,用静态列表的方式也不是很好,如果用户量庞大,会不会出什么问题呢,我具体没研究过。一般的方案,是放在专门的缓存服务器存储,或者NOSQL数据库存储也可以吧,方案有很多,由于没有具体做过也不敢多费口舌。这个思路是没问题的,当然也会有更好的方法吧。
ASP.NET SingalR 点对点聊天实现思路总结的更多相关文章
- ASP.NET SingalR + MongoDB 实现简单聊天室(一):搭建基本框架
ASP.NET SingalR不多介绍.让我介绍不如看官网,我这里就是直接上源代码,当然代码还是写的比较简单的,考虑的也少,希望各位技友多多提意见. 先简单介绍聊天室功能: 用户加入聊天室,自动给用户 ...
- Activemq mqtt 点对点聊天实现(转载)
我这想到一个点对点聊天的方法,不用没割人都建立一个topic了,思路还是自定义一个分发策略,具体如下: 1. 建立一个topic,所有人都用匹配订阅的方式订阅以该topic为头的topic,例如:所 ...
- Linux 网络编程详解三(p2p点对点聊天)
//p2p点对点聊天多进程版--服务器(信号的使用) #include <stdio.h> #include <stdlib.h> #include <string.h& ...
- AngularJS使用OData请求ASP.NET Web API资源的思路
本篇整理AngularJS使用OData请求ASP.NET Web API资源的思路. 首先给ASP.NET Web API插上OData的翅膀,通过NuGet安装OData. 然后,给control ...
- Angular 2的HTML5 pushState在ASP.NET Core上的解决思路
Angular 2的HTML5 pushState在ASP.NET Core上的解决思路 正如Angular 2在Routing & Navigation中所提及的那样,Angular 2是推 ...
- ASP.NET SingalR + MongoDB 实现简单聊天室(三):实现用户群聊,总结完善
前两篇已经介绍的差不多了,本篇就作为收尾. 使用hub方法初始化聊天室的基本步骤和注意事项 首先确保页面已经引用了jquery和singalR.js还有对应的hubs文件,注意,MVC框架有时会将jq ...
- ASP.NET SingalR + MongoDB 实现简单聊天室(二):实现用户信息、聊天室初始化,聊天信息展示完善
第一篇已经介绍了一大半了,下面就是详细业务了,其实业务部分要注意的地方有几个,剩下的就是js跟html互动处理. 首先在强调一下,页面上不可缺少的js:jquery,singalR.js,hubs . ...
- ASP.NET 大文件下载的实现思路及代码
文件下载是一个网站最基本的功能,ASP.NET网站的文件下载功能实现也很简单,但是如果遇到大文件的下载而不做特殊处理的话,那将会出现不可预料的后果.本文就基于ASP.NET提供大文件下载的实现思路及代 ...
- 使用SignalR+Asp.net创建实时聊天应用程序
一.概述: 使用 ASP.NET 那么 SignalR 2 创建一个实时聊天应用程序.将 SignalR 添加 MVC 5 应用程序中,并创建聊天视图发送并显示消息. 在Demo中,将学习Signal ...
随机推荐
- Silverlight & Blend动画设计系列八:拖放(Drag-Drop)操作与拖放行为(DragBehavior)
在Silverlight中自身并没有提供拖放功能的相关实现,要实现拖放功能得借助其事件支持(MouseLeftButtonDown.MouseLeftButtonUp和MouseMove)来完成,实际 ...
- redis(1)简介
一.nosql简介 RDBMS(关系型数据库)提供的结构化编程,让数据建模以及应用程序编程变得非常简单,带来了非常高的经济效益,并且学习成本也比较低.但在当今数据大爆炸时代,每时每刻都会海量的数据产生 ...
- HttpContext.Current.Request.RawUrl是什么意思?
原始 URL 定义为 URL 中域信息之后的部分.在 URL 字符串 http://www.contoso.com/articles/recent.aspx 中,原始 URL 为/articles/r ...
- mysql 笔记3
--建库create database dsdb DEFAULT CHARACTER set utf8 collate utf8_general_ci;/*删除数据库drop DATABASE 数据库 ...
- 使用JS完成首页轮播图效果
获取document.getElementById("id名称"); 事件onload 定时操作setInterval("changeImg()",3000); ...
- react 使用fortawesome字体图标
fontawesome 官方使用教程=>点我 npm i --save @fortawesome/fontawesome-svg-core@prerelease \ npm i --save @ ...
- [Java]private, public,protected,friendly的区别(转载)一下子就记住了
http://teddyboy200382.blog.163.com/blog/static/320112002008825112549780/ 说明这四个关键字之前,我想就 class 之间的关系做 ...
- 谈谈CSS性能
CSS性能优化 1.衡量属性和布局的消耗代价: 2.探索W3C的性能优化新规范: 3.用测试数据判断优化策略. 慎重选择高消耗的样式 1.box-shadows; 2.border-radius; 3 ...
- 多线程 读写锁SRWLock
在<秒杀多线程第十一篇读者写者问题>文章中我们使用事件和一个记录读者个数的变量来解决读者写者问题.问题虽然得到了解决,但代码有点复杂.本篇将介绍一种新方法——读写锁SRWLock来解决这一 ...
- webstorm javascript IDE调试
webstorm是我见过的前端开发调试最好用的IDE工具了,它不仅具有强大的编辑,代码查阅引用功能,更有强大的js调试功能,这是任何通过firebug,chrome devtool,console.l ...