.net core 使用SignalR实现实时通信

这几天在研究SignalR,网上大部分的例子都是聊天室,我的需求是把服务端的信息发送给前端展示。并且需要实现单个用户推送。

用户登录我用的是ClaimsIdentity,这里就不多解释,如果不是很了解,可以看这篇文章https://www.cnblogs.com/zhangjd/p/11332558.html

推荐https://www.cnblogs.com/laozhang-is-phi/p/netcore-vue-signalr.html#tbCommentBody这个博客,写的很详细,并且附有Dome

一、后端实现

1、引用SignalR包

Install-Package Microsoft.AspNetCore.SignalR

2、声明一个类来记录用户的连接信息。

1     public class SignalRModel
2     {
3         public static Dictionary<string, SignalRStatus> StaticList = new Dictionary<string, SignalRStatus>();
4         public static Dictionary<string, string> SignalRList { get; set; } = new Dictionary<string, string>();
5     }

3、声明Hub,这里我重写了连接和断开方法,用来绑定用户和连接的ConnectionId。(这个比较复杂,是因为我程序中执行的第三方程序,需要实时输出当前执行的程序的日志。但是调用的执行不可能直接写在控制器里,这样调用我没办法获取当前用户的登录Id。然后我就在发起连接和断开连接的方法处理了。)

 1 public class ChatHub : Hub
 2     {
 3         /// <summary>
 4         /// 连接成功
 5         /// </summary>
 6         /// <returns></returns>
 7         public override Task OnConnectedAsync()
 8         {
 9             var id = this.Context.ConnectionId;
10             var claimNameIdentifier = this.Context.User.Claims.FirstOrDefault(s => s.Type == ClaimTypes.NameIdentifier)?.Value;
11             SignalRModel.SignalRList.Add(id, claimNameIdentifier);
12             if (SignalRModel.StaticList.Any(s => s.Key.Equals(claimNameIdentifier)))
13             {
14                 SignalRModel.StaticList.Remove(claimNameIdentifier);
15             }
16             SignalRModel.StaticList.Add(claimNameIdentifier, SignalRStatus.Open);
17             return base.OnConnectedAsync();
18         }
19         /// <summary>
20         /// 断开连接
21         /// </summary>
22         public override Task OnDisconnectedAsync(Exception exception)
23         {
24             var id = this.Context.ConnectionId;
25             var claimNameIdentifier = this.Context.User.Claims.FirstOrDefault(s => s.Type == ClaimTypes.NameIdentifier)?.Value;
26             SignalRModel.SignalRList.Remove(id);
27             SignalRModel.StaticList.Remove(claimNameIdentifier);
28             return base.OnDisconnectedAsync(exception);
29         }
30         /// <summary>
31         /// 发送消息
32         /// </summary>
33         /// <param name="user"></param>
34         /// <param name="message"></param>
35         /// <returns></returns>
36         public async Task SendMessage(string user, string message)
37         {
38             await Clients.All.SendAsync("ReceiveMessage", user, message);
39         }
40     }

4、在程序启动的时候,把记录用户连接信息的类,注入成单例,保存用户和连接的对应关系,方便单个通信。

1   services.AddSingleton<SignalRModel>(provider =>
2   {
3       return new SignalRModel();
4   });

5、配置

1)、在ConfigureServices中加入

services.AddSignalR();//要写在addmvc()前面services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);

2)、在Configure中加入

app.UseMvc();app.UseSignalR(routes =>
{
   routes.MapHub<ChatHub>("/api/chatHub");
});//要写在UseMvc后面

6、这里我写了后端两个接口来发送消息,区别在于第一个是群发,第二个是针对一个连接发送的。

 1         [HttpGet("SendAll")]
 2         public IActionResult SendAll()
 3         {
 4             _hubContext.Clients.All.SendAsync("ReceiveUpdate", "推送全部人").Wait();
 5             return Ok("推送全部人");
 6         }
 7         [HttpGet("SendOnly")]
 8         public IActionResult SendOnly()
 9         {
10             var claimNameIdentifier = User.Claims.FirstOrDefault(s => s.Type == ClaimTypes.NameIdentifier)?.Value;
11             if (string.IsNullOrEmpty(claimNameIdentifier))
12             {
13                 return Ok(new { code = ResultCode.NotLogin, message = "用户未登陆!" });
14             }
15             _hubContext.Clients.Clients(claimNameIdentifier).SendAsync("ReceiveUpdate", DateTime.Now).Wait();
16             return Ok("推送当前登录用户");
17         }

7、我项目实际用到的是这样的,给当前登录用户发送日志消息,判断连接是否断开,如果断开需要获取前面写的日志,发送给前端之后,把连接的状态改成连接中,后面就正常发送。

 1    foreach (var item in SignalRModel.SignalRList.Where(s => s.Value.Equals(userId.ToString())).ToList())
 2    {
 3       if (SignalRModel.StaticList.Any(s => s.Key.Equals(userId.ToString()) && s.Value == SignalRStatus.Open))
 4       {
 5          if (SignalRModel.StaticList.Any(s => s.Key.Equals(userId.ToString())))
 6          {
 7               SignalRModel.StaticList.Remove(userId.ToString());
 8          }
 9          SignalRModel.StaticList.Add(userId.ToString(), SignalRStatus.working);
10          _hubContext.Clients.Client(item.Key).SendAsync("ReceiveUpdate", FileHelper.ReadFile(Path.Combine(filePath, "tls_simplify.txt"), Encoding.UTF8)).Wait();
11       }
12       _hubContext.Clients.Client(item.Key).SendAsync("ReceiveUpdate", args.Data).Wait();
13    }

二、前端vue

1、安装依赖包

npm install @aspnet/signalr

2、示例页面

  1 <template>
  2     <section>
  3         <div style="display: none1">
  4             <el-form ref="form" label-width="80px" @submit.prevent="onSubmit"
  5                      style="margin:20px;width:60%;min-width:600px;">
  6                 <el-form-item label="用户名">
  7                     <el-input v-model="userName"></el-input>
  8                 </el-form-item>
  9                 <el-form-item label="密码">
 10                     <el-input v-model="userMessage"></el-input>
 11                 </el-form-item>
 12             </el-form>
 13             <ul v-for="(item, index) in messages" v-bind:key="index + ‘itemMessage‘">
 14                 <li><b>Name: </b>{{item.user}}</li>
 15                 <li><b>Message: </b>{{item.message}}</li>
 16             </ul>
 17             <p>
 18             <b>后台发送消息: </b>{{this.postMessage}}
 19             </p>
 20             <el-button type="primary" @click="submitCard">登录</el-button>
 21             <el-button type="primary" @click="getLogs">查询</el-button>
 22         </div>
 23     </section>
 24 </template>
 25
 26 <script>
 27
 28     import * as signalR from "@aspnet/signalr";
 29
 30     export default {
 31       name: ‘Dashboard‘,
 32         data() {
 33             return {
 34                 filters: {
 35                     LinkUrl: ‘‘
 36                 },
 37                 listLoading: true,
 38                 postMessage: "",
 39                 userName: "Tom",
 40                 userMessage: "123",
 41                 connection: "",
 42                 messages: [],
 43                 t: ""
 44
 45             }
 46         },
 47         methods: {
 48             getRoles() {
 49                 let thisvue=this;
 50                 let para = {
 51                     page: this.page,
 52                     key: this.filters.LinkUrl
 53                 };
 54                 this.listLoading = true;
 55                 thisvue.connection.start().then(() => {
 56                    thisvue.connection.invoke(‘GetLatestCount‘, 1).catch(function (err) {
 57                    return console.error(err);
 58                 });
 59             });
 60             },
 61             submitCard: function () {
 62                 if (this.userName && this.userMessage) {
 63                     this.connection.invoke(‘SendMessage‘, this.userName, this.userMessage).catch(function (err) {
 64                         return console.error(err);
 65                     });
 66
 67                 }
 68             },
 69             getLogs: function () {
 70                 this.listLoading = true;
 71                 this.connection.invoke(‘GetLatestCount‘, 1).catch(function (err) {
 72                     return console.error(err);
 73                 });
 74             }
 75         },
 76         created: function () {
 77             let thisVue = this;
 78             thisVue.connection = new signalR.HubConnectionBuilder()
 79                 .withUrl(‘http://localhost:5000/api/chatHub‘)
 80                 .configureLogging(signalR.LogLevel.Information)
 81                 .build();
 82             thisVue.connection.on(‘ReceiveMessage‘, function (user, message) {
 83                 thisVue.messages.push({user, message});
 84             });
 85
 86             thisVue.connection.on(‘ReceiveUpdate‘, function (update) {
 87                 console.info(‘update success!‘)
 88                 thisVue.listLoading = false;
 89                 thisVue.postMessage = update;
 90                 window.clearInterval(this.t)
 91             })
 92         },
 93         mounted() {
 94             this.getRoles();
 95         },
 96         beforeDestroy() {
 97             window.clearInterval(this.t)
 98             this.connection.stop();
 99         }
100     }
101 </script>
102
103 <style scoped>
104     .demo-table-expand {
105         font-size: 0;
106     }
107
108     .demo-table-expand label {
109         width: 90px;
110         color: #99a9bf;
111     }
112
113     .demo-table-expand .el-form-item {
114         margin-right: 0;
115         margin-bottom: 0;
116         width: 30%;
117     }
118
119     .EXC {
120         color: red;
121     }
122 </style>

原文地址:https://www.cnblogs.com/zhangjd/p/11332849.html

时间: 2024-10-30 06:40:10

.net core 使用SignalR实现实时通信的相关文章

一步一步学习SignalR进行实时通信_1_简单介绍

原文:一步一步学习SignalR进行实时通信_1_简单介绍 一步一步学习SignalR进行实时通信\_1_简单介绍 SignalR 一步一步学习SignalR进行实时通信_1_简单介绍 前言 SignalR介绍 支持的平台 相关说明 OWIN 结束语 参考文献 前言 本来前几个月想写一系列的关于SignalR的文章,但是由于在做项目,时间非常的紧急,花了1天的时间大致了解了下SignalR,并实现了个在线聊天的小功能,本来记录一系列关于SignalR的文章,没想到写了MVC5使用SignalR进

一步一步学习SignalR进行实时通信_8_案例2

原文:一步一步学习SignalR进行实时通信_8_案例2 一步一步学习SignalR进行实时通信\_8_案例2 SignalR 一步一步学习SignalR进行实时通信_8_案例2 前言 配置Hub 建立DrawingHub 页面 javascript 实现效果 结束语 参考文献 前言 这讲分析一个案例,在一个画板上画画实时在其他客户端上显示. 配置Hub 在Startup中进行配置: public void Configuration(IAppBuilder app) { app.MapSign

一步一步学习SignalR进行实时通信_5_Hub

原文:一步一步学习SignalR进行实时通信_5_Hub 一步一步学习SignalR进行实时通信\_5_Hub SignalR 一步一步学习SignalR进行实时通信_5_Hub 前言 Hub命名规则 Hub封装好的常用方法 Hub常用方法解释 保持状态 前后台交互 结束语 参考文献 前言 上一讲,我们简单的介绍了下Hub的配置以及实现方法,这一将我希望把更多的细节梳理清楚,不至于让大家在细节上面摸不着头脑,理解深了,那么做项目自然就会相对轻松一些. Hub命名规则 Hub与Persistent

一步一步学习SignalR进行实时通信_3_通过CORS解决跨域

原文:一步一步学习SignalR进行实时通信_3_通过CORS解决跨域 一步一步学习SignalR进行实时通信\_3_通过CORS解决跨域 SignalR 一步一步学习SignalR进行实时通信_3_通过CORS解决跨域 前言 关于start()的补充 跨域解决方案 JSONP CORS CORS跨域演示 结束语 参考文献 前言 这周工作比较忙,一直没有时间学习SignalR,大致希望一周能写一篇关于SignalR的文章.上一篇用Persistent Connections方式实现了个简单的在线

一步一步学习SignalR进行实时通信_2_Persistent Connections

原文:一步一步学习SignalR进行实时通信_2_Persistent Connections 一步一步学习SignalR进行实时通信\_2_Persistent Connections SignalR 一步一步学习SignalR进行实时通信_2_Persistent Connections 前言 安装 Persistent Connections 映射并配置持久连接 结束语 参考文献 前言 上一篇文章简单的介绍了下SignalR,从此篇文章就开始对SignalR进行剖析.在介绍Persiste

Asp.Net Core使用SignalR进行服务间调用

原文:Asp.Net Core使用SignalR进行服务间调用 网上查询过很多关于ASP.NET core使用SignalR的简单例子,但是大部分都是简易聊天功能,今天心血来潮就搞了个使用SignalR进行服务间调用的简单DEMO. 至于SignalR是什么我就不多说了,微软官方文档也不少. 第一步新建项目 所有VS开发第一步都是新建一个解决方案哈,这里我就不多介绍如何新建项目啦~~ 开发环境,VS2017,.NET CORE 2.1 新建两个asp.net core项目 如此简单的操作大家都懂

一步一步学习SignalR进行实时通信_7_非代理

目录 一步一步学习SignalR进行实时通信_7_非代理 前言 代理与非代理 建立连接 调用方法 维持状态 从服务器接收 结束语 参考文献 一步一步学习SignalR进行实时通信_7_非代理 标签(空格分隔): SignalR 前言 距离上次写博客已经一个多月了,一直想抽空写,却一直没时间写.现在紧接着要开始毕业设计了,工作的同时还要抽时间完成毕业设计,心也是有些累.由于自己是个.NET迷,自己的工作也是.net开发,老师给的毕业设计百分之八九十都是安卓java相关,虽然之前也学过但是自己还是喜

ASP.NET Core 2.2 基础知识(十六) SignalR 概述

原文:ASP.NET Core 2.2 基础知识(十六) SignalR 概述 我一直觉得学习的最好方法就是先让程序能够正常运行,才去学习他的原理,剖析他的细节. 就好像这个图: 所以,我们先跟着官方文档,创建一个 SignalR 应用: https://docs.microsoft.com/zh-cn/aspnet/core/tutorials/signalr?view=aspnetcore-2.2&tabs=visual-studio 这个例子一共涉及到下面几个步骤: 自定义中心 ChatH

.Net Core SignalR 初体验

前言 Asp.Net SignalR已经出来很久了,但是一直没有静下心来好好看看.昨天花了几个小时的时间看了下.首先借鉴了官方文档,如何搭建一个SignalR的Demo. 参考文章:https://docs.microsoft.com/zh-cn/aspnet/core/tutorials/signalr?view=aspnetcore-2.1&tabs=visual-studio SignalR地址:https://github.com/aspnet/SignalR 所以为了快速搭建和体验.N