gpt4 book ai didi

SignalR中丰富多彩的消息推送方式的实现代码

转载 作者:qq735679552 更新时间:2022-09-29 22:32:09 28 4
gpt4 key购买 nike

CFSDN坚持开源创造价值,我们致力于搭建一个资源共享平台,让每一个IT人在这里找到属于你的精彩世界.

这篇CFSDN的博客文章SignalR中丰富多彩的消息推送方式的实现代码由作者收集整理,如果你对这篇文章有兴趣,记得点赞哟.

在上一篇 SignalR 文章中,演示了如何通过 SignalR 实现了简单的聊天室功能;本着简洁就是美的原则,这一篇我们也来聊聊在 SignalR 中的用户和组的概念,理解这些基础知识有助于更好的开发基于 SignalR 的应用,通过对用户和分组的理解,进一步扩展出对用户和分组的管理,以及消息推送的各种方式,为全面接入 SignalR 做准备.

1. 用户 。

在 SignalR 中,用户表示连接,一个用户代表一个连接,一个“系统用户”可以创建多个连接身份,通过函数集线器,可以给一个用户的所有连接发送消息;比如一个“系统用户”拥有多个连接,这些连接分别是 Web连接、AndroId手机客户端连接,IOS手机客户端连接、或者其它客户端连接,“系统用户”分别登录了这些客户端,同时创建了多个连接;默认情况下这些连接都通过 ClaimTypes.NameIdentifier 在 ClaimsPrincipal 于用户标识进行关联.

** 注意:用户标识符是区分大小写的,为了实现一个客户多个连接,本例还简单实现了一个基于 ClaimsIdentity 登录接口,算是意外惊喜.

1.1 用户连接管理 。

为了直观的观察到用户是可以拥有多连接的,需要建立一个本地静态对象,用于存储用户连接 。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
public class WeChatHub : Hub
  {
   public Dictionary< string , List< string >> UserList { get ; set ; } = new Dictionary< string , List< string >>();
 
   public void Send(ChatMessage body)
   {
    Clients.All.SendAsync( "Recv" , body);
   }
 
   public override Task OnConnectedAsync()
   {
    var userName = this .Context.User.Identity.Name;
    var connectionId = this .Context.ConnectionId;
    if (!UserList.ContainsKey(userName))
    {
     UserList[userName] = new List< string >();
     UserList[userName].Add(connectionId);
    }
    else if (!UserList[userName].Contains(connectionId))
    {
     UserList[userName].Add(connectionId);
    }
    Console.WriteLine( "哇,有人进来了:{0},{1},{2}" , this .Context.UserIdentifier, this .Context.User.Identity.Name, this .Context.ConnectionId);
    return base .OnConnectedAsync();
   }
 
   public override Task OnDisconnectedAsync(Exception exception)
   {
    var userName = this .Context.User.Identity.Name;
    var connectionId = this .Context.ConnectionId;
    if (UserList.ContainsKey(userName))
    {
     if (UserList[userName].Contains(connectionId))
     {
      UserList[userName].Remove(connectionId);
     }
    }
 
    Console.WriteLine( "靠,有人跑路了:{0}" , this .Context.ConnectionId);
    return base .OnDisconnectedAsync(exception);
   }
  }

上面的代码包含了一个内部成员 UserList,用于存储用户的每个连接,在用户进行 SignalR 连接时,将当前连接存储到 UserList 中,当连接断开的时候,将当前连接从 UserList 中删除。这样就实现了一个简单的用户连接管理.

在上面的代码中,当前用户昵称是根据 var userName = this.Context.User.Identity.Name; 这行代码获取的,为了取得这个用户昵称,我们实现了一个简单的 UserIdentity 登录,然后将 User 信息写入到 Cookie 中,最后才可以通过 var userName = this.Context.User.Identity.Name; 获得当前登录用户昵称(熟悉 ID 登录流程的同学应该不会感到陌生,实际上我也很少使用 ID 验证) 。

1.2 给单个用户发送消息 。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
[Authorize(Roles = "User" )]
[HttpPost( "SendToUser" )]
public async Task<IActionResult> SendToUser([FromBody] UserInfoViewModel model)
{
  ChatMessage message = new ChatMessage()
  {
   Type = 1,
   Content = model.Content,
   UserName = model.UserName
  };
 
  if ( this .chatHub.UserList.ContainsKey(model.UserName))
  {
   var connections = this .chatHub.UserList[model.UserName].First();
   await this .chatHub.Clients.Client(connections).SendAsync( "Recv" , new object [] { message });
  }
 
  return Json( new { Code = 0 });
}

在 UserController 中,定义了上面的接口 SendToUser ,客户端传入用户昵称和消息,然后服务端就会去根据 ChatHub.UserList 成员查找目标用户的连接信息,最后,通过 SendAsync 将消息推送到目标客户端连接中.

2. 分组 。

分组的概念类似于聊天室,每个房间就是一个独立的分组,用户可以选择加入 A 房间,也可以选择加入 B 房间,如果业务允许,一个用户还可以加入多个分组(房间),通过使用分组对用户进行管理,可以实现一个或者多个聊天房间,用户可以加入分组,也可以将用户从分组中删除(类似离开房间),这里的用户并发真正意义上的“系统用户”,而是指系统用户创建的那些 SignalR连接.

** 注意:当连接断开后重新发起连接的时候,SignalR 不会保留组成员身份,必须重新加入分组.

下面的代码演示了如何对分组进行操作,要对分组进行操作,主要包含三个方面:

2.1 加入分组 。

?
1
2
3
4
public async Task AddToGroupAsync( string groupName)
  {
   await Groups.AddToGroupAsync( this .Context.ConnectionId, groupName);
  }

2.2 离开分组 。

?
1
2
3
4
public async Task RemoveFromGroupAsync( string groupName)
  {
   await Groups.RemoveFromGroupAsync( this .Context.ConnectionId, groupName);
  }

2.3 发送消息到指定分组 。

?
1
2
3
4
public async Task SendToGroupAsync( string groupName, ChatMessage message)
  {
   await Clients.Group(groupName).SendAsync(groupName, new object [] { message });
  }

对分组的操作非常的简单,几乎都是一行代码的事情,不得不说,微软的封装实在是太好了.

3. SignalR的推送消息的其它方式 。

通过上面对用户和分组的学习,再去扩展学习其它推送消息的方式,就非常的好理解和上手,在 SignalR 内部还有多种推送消息的方式,他们分别是 。

3.1 All(全站推送) 。

3.2 Others(全站推送排除自己) 。

3.3 OthersInGroup(指定分组推送,排除自己) 。

3.4 AllExcept(除指定列表外的所有人) 。

3.5 演示代码 。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
List< string > blackList = new List< string >();
  public async Task OtherSendAsync(ChatMessage body)
  {
   // 给当前连接到 Hub 上的所有连接发送消息,相当于广播
   await Clients.All.SendAsync( "Recv" , body);
 
   // 给当前连接对象发送消息
   await Clients.Caller.SendAsync( "Recv" , body);
 
   // 给其它所有连接的客户端发送消息,除了当前正在连接的客户端
   await Clients.Others.SendAsync( "Recv" , body);
 
   // 查找当前所有连接的客户端(排除自己),如果是已加入此分组,则给他们推送消息
   await Clients.OthersInGroup( "groupName" ).SendAsync( "Recv" , body);
 
   // 给除了 blackList(黑名单)之外的所有人发送消息
   await Clients.AllExcept(blackList).SendAsync( "Recv" , body);
  }

4. 一个简单的示例 。

本示例代码包含两个简单的界面 。

4.1 登录 。

SignalR中丰富多彩的消息推送方式的实现代码

4.2 各种方式发送消息 。

SignalR中丰富多彩的消息推送方式的实现代码

结束语 。

最近在做一个开源项目,还处于试用阶段,准备写个使用的 WIKI 出来,看看大家是否感兴趣,此 SingalR 系列只能不定期更新了,抱歉.

演示代码下载 。

已托管到 GitHub 仓库 。

https://github.com/lianggx/Examples/tree/master/SignalR/Ron.SignalRLesson2 。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我.

原文链接:http://www.cnblogs.com/viter/p/10638331.html 。

最后此篇关于SignalR中丰富多彩的消息推送方式的实现代码的文章就讲到这里了,如果你想了解更多关于SignalR中丰富多彩的消息推送方式的实现代码的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com