重庆分公司,新征程启航
为企业提供网站建设、域名注册、服务器等服务
这篇文章将为大家详细讲解有关使用SignalR怎么实现丰富多彩的消息推送方式,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。
站在用户的角度思考问题,与客户深入沟通,找到鄂州网站设计与鄂州网站推广的解决方案,凭借多年的经验,让设计与互联网技术结合,创造个性化、用户体验好的作品,建站类型包括:做网站、成都网站设计、企业官网、英文网站、手机端网站、网站推广、域名申请、网络空间、企业邮箱。业务覆盖鄂州地区。1. 用户
在 SignalR 中,用户表示连接,一个用户代表一个连接,一个“系统用户”可以创建多个连接身份,通过函数集线器,可以给一个用户的所有连接发送消息;比如一个“系统用户”拥有多个连接,这些连接分别是 Web连接、AndroId手机客户端连接,IOS手机客户端连接、或者其它客户端连接,“系统用户”分别登录了这些客户端,同时创建了多个连接;默认情况下这些连接都通过 ClaimTypes.NameIdentifier 在 ClaimsPrincipal 于用户标识进行关联。
** 注意:用户标识符是区分大小写的,为了实现一个客户多个连接,本例还简单实现了一个基于 ClaimsIdentity 登录接口,算是意外惊喜。
1.1 用户连接管理
为了直观的观察到用户是可以拥有多连接的,需要建立一个本地静态对象,用于存储用户连接
public class WeChatHub : Hub { public Dictionary> UserList { get; set; } = new Dictionary >(); 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 (); 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 给单个用户发送消息
[Authorize(Roles = "User")] [HttpPost("SendToUser")] public async TaskSendToUser([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 加入分组
public async Task AddToGroupAsync(string groupName) { await Groups.AddToGroupAsync(this.Context.ConnectionId, groupName); }
2.2 离开分组
public async Task RemoveFromGroupAsync(string groupName) { await Groups.RemoveFromGroupAsync(this.Context.ConnectionId, groupName); }
2.3 发送消息到指定分组
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 演示代码
ListblackList = new List (); 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); }
关于使用SignalR怎么实现丰富多彩的消息推送方式就分享到这里了,希望以上内容可以对大家有一定的帮助,可以学到更多知识。如果觉得文章不错,可以把它分享出去让更多的人看到。