前一段时间写了一个简单的聊天室,是群聊的方式。博客地址: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 点对点聊天实现思路总结的更多相关文章

  1. ASP.NET SingalR + MongoDB 实现简单聊天室(一):搭建基本框架

    ASP.NET SingalR不多介绍.让我介绍不如看官网,我这里就是直接上源代码,当然代码还是写的比较简单的,考虑的也少,希望各位技友多多提意见. 先简单介绍聊天室功能: 用户加入聊天室,自动给用户 ...

  2. Activemq mqtt 点对点聊天实现(转载)

    我这想到一个点对点聊天的方法,不用没割人都建立一个topic了,思路还是自定义一个分发策略,具体如下: 1.  建立一个topic,所有人都用匹配订阅的方式订阅以该topic为头的topic,例如:所 ...

  3. Linux 网络编程详解三(p2p点对点聊天)

    //p2p点对点聊天多进程版--服务器(信号的使用) #include <stdio.h> #include <stdlib.h> #include <string.h& ...

  4. AngularJS使用OData请求ASP.NET Web API资源的思路

    本篇整理AngularJS使用OData请求ASP.NET Web API资源的思路. 首先给ASP.NET Web API插上OData的翅膀,通过NuGet安装OData. 然后,给control ...

  5. Angular 2的HTML5 pushState在ASP.NET Core上的解决思路

    Angular 2的HTML5 pushState在ASP.NET Core上的解决思路 正如Angular 2在Routing & Navigation中所提及的那样,Angular 2是推 ...

  6. ASP.NET SingalR + MongoDB 实现简单聊天室(三):实现用户群聊,总结完善

    前两篇已经介绍的差不多了,本篇就作为收尾. 使用hub方法初始化聊天室的基本步骤和注意事项 首先确保页面已经引用了jquery和singalR.js还有对应的hubs文件,注意,MVC框架有时会将jq ...

  7. ASP.NET SingalR + MongoDB 实现简单聊天室(二):实现用户信息、聊天室初始化,聊天信息展示完善

    第一篇已经介绍了一大半了,下面就是详细业务了,其实业务部分要注意的地方有几个,剩下的就是js跟html互动处理. 首先在强调一下,页面上不可缺少的js:jquery,singalR.js,hubs . ...

  8. ASP.NET 大文件下载的实现思路及代码

    文件下载是一个网站最基本的功能,ASP.NET网站的文件下载功能实现也很简单,但是如果遇到大文件的下载而不做特殊处理的话,那将会出现不可预料的后果.本文就基于ASP.NET提供大文件下载的实现思路及代 ...

  9. 使用SignalR+Asp.net创建实时聊天应用程序

    一.概述: 使用 ASP.NET 那么 SignalR 2 创建一个实时聊天应用程序.将 SignalR 添加 MVC 5 应用程序中,并创建聊天视图发送并显示消息. 在Demo中,将学习Signal ...

随机推荐

  1. ASP.NET MVC4 新手入门教程特别篇之一----Code First Migrations更新数据库结构(数据迁移)修改Entity FrameWork 数据结构(不删除数据)

    背景 code first起初当修改model后,要持久化至数据库中时,总要把原数据库给删除掉再创建(DropCreateDatabaseIfModelChanges),此时就会产生一个问题,当我们的 ...

  2. JFrame自适应大小

    pack();函数调用PreferedSize(); 所以对于组件要setPreferedSize();

  3. java温故而知新(8)反射机制

    一.什么是反射机制  简单的来说,反射机制指的是程序在运行时能够获取自身的信息.在java中,只要给定类的名字, 那么就可以通过反射机制来获得类的所有信息. 二.哪里用到反射机制  有些时候,我们用过 ...

  4. thinkphp多表联合查询

    1.两个表查询 $userid=session('user.id'); $user = M('cuser'); $data = $user->field('projectno')->whe ...

  5. express的proxy实现前后端分离

    var express = require('express') var proxy = require('http-proxy-middleware') var app = express() ap ...

  6. 洛谷P3952 时间复杂度(模拟)

    题意 题目链接 Sol 咕了一年的题解..就是个模拟吧 考场上写的递归也是醉了... 感觉一年自己进步了不少啊..面向数据编程的能力提高了不少 #include<bits/stdc++.h> ...

  7. 工作中常用的sql语句以及知识整理

    一.常用的sql语句 1.建表语句 create table tabname(colname1 type1 [not null][primary key], colname2 type2,...) 根 ...

  8. MongoDB 删除集合

    drop() 方法 MongoDB 的 db.collection.drop() 是用来从数据库中删除一个集合. 语法: drop() 命令的基本语法如下 db.COLLECTION_NAME.dro ...

  9. 日常捕获的野生知识 - javascript 与 类

    javascript 并不提供类这样方便实用的面向对象类型,今天学习到了,直接上代码: <!DOCTYPE html> <html lang="en"> & ...

  10. hive配置参数的说明:

    hive.ddl.output.format:hive的ddl语句的输出格式,默认是text,纯文本,还有json格式,这个是0.90以后才出的新配置: hive.exec.script.wrappe ...