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 ...
随机推荐
- sqlserver - FOR XML PATH
FOR XML PATH 有的人可能知道有的人可能不知道,其实它就是将查询结果集以XML形式展现,有了它我们可以简化我们的查询语句实现一些以前可能需要借助函数活存储过程来完成的工作.那么以一个实例为主 ...
- [javaEE] JDBC快速入门
JDBC:Java Data Base Connectivity java数据库连接 1.组成JDBC的两个包:主要是接口 java.sql javax.sql 2.相应JDBC的数据库实现 在tom ...
- Java SortedSet为什么可以实现自动排序?
Set中的SortedSet(SortedSet为TreeSet的实现接口),它们之间的继承关系如下: java.util.Set; java.util.SortedSet; java.util.Tr ...
- Tomcat添加用户
在conf目录下tomcat-users.xml文件里添加如下代码: <role rolename="manager-gui"/> <user username= ...
- Bzoj3105:[CQOI2013]新Nim游戏
题面 传送门 Sol 也是拿出一些数,使剩下的异或起来不为\(0\) 而线性基内的数异或不出\(0\) 那么从大到小加到线性基内 然后中途为\(0\)了,就取走它 这样我们使最大的在线性基内,剩下的是 ...
- css模仿百度首页
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...
- (转) AJAX POST&跨域 解决方案 - CORS
跨域是我在日常面试中经常会问到的问题,这词在前端界出现的频率不低,主要原因还是由于安全限制(同源策略, 即JavaScript或Cookie只能访问同域下的内容),因为我们在日常的项目开发时会不可避免 ...
- MySQL性能优化的20+条经验
1. 为查询缓存优化你的查询 大多数的MySQL服务器都开启了查询缓存.这是提高性最有效的方法之一,而且这是被MySQL的数据库引擎处理的.当有很多相同的查询被执行了多次的时候,这些查询结果会被放到一 ...
- 微信小程序支付返回信息为空
1.昨天公司说要实现微信小程序的支付,于是看了下微信小程序的开发api文档,和之前的app 端以及pc端基本相似:于是让他们把参数改了下,把之前的trade_type 由 app 改成 小程序要求的 ...
- Mysql 启动失败常见错误
各位可以按照顺序逐条拍错. mysql启动时报错:Starting MySQL... ERROR! The server quit without updating PID file (/opt/my ...