SignalR 应用实例

后台

  1 using Microsoft.AspNetCore.Authorization;
  2 
  3 using Microsoft.AspNetCore.SignalR;
  4 
  5 using PaddypestChart.DataAccess.Core.IService.IAPP;
  6 
  7 using System;
  8 
  9 using System.Collections.Generic;
 10 
 11 using System.Security.Claims;
 12 
 13 using System.Threading.Tasks;
 14 
 15 using Utility.src.Redis;
 16 
 17  
 18 
 19 namespace Microsoft.AspNetCore.Builder
 20 
 21 {
 22 
 23     /// <summary>
 24 
 25     /// 
 26 
 27     /// </summary>
 28 
 29     [Authorize]
 30 
 31     public class ChatHub : Hub
 32 
 33     {
 34 
 35         /// <summary>
 36 
 37         /// 
 38 
 39         /// </summary>
 40 
 41         private readonly object balanceLock = new object();
 42 
 43  
 44 
 45         /// <summary>
 46 
 47         /// 是否系统启动后第一次连接
 48 
 49         /// </summary>
 50 
 51         private static bool FirstConnected = true;
 52 
 53  
 54 
 55         /// <summary>
 56 
 57         /// 
 58 
 59         /// </summary>
 60 
 61         IOnline online;
 62 
 63  
 64 
 65         /// <summary>
 66 
 67         /// 
 68 
 69         /// </summary>
 70 
 71         ICommonUser commonUser;
 72 
 73  
 74 
 75         /// <summary>
 76 
 77         /// 构造函数
 78 
 79         /// </summary>
 80 
 81         /// <param name="online">服务注入</param>
 82 
 83         /// <param name="commonUser">服务注入</param>
 84 
 85         public ChatHub(IOnline online, ICommonUser commonUser)
 86 
 87         {
 88 
 89             this.online = online;
 90 
 91             this.commonUser = commonUser;
 92 
 93         }
 94 
 95  
 96 
 97         /// <summary>
 98 
 99         /// 向指定用户推送消息
100 
101         /// </summary>
102 
103         /// <param name="user"></param>
104 
105         /// <param name="message"></param>
106 
107         /// <returns></returns>
108 
109         public async Task SendMessage(string user, string message) => await Clients.User(user).SendAsync("ReceiveMessage", message);
110 
111  
112 
113         /// <summary>
114 
115         /// 连接触发
116 
117         /// </summary>
118 
119         /// <returns></returns>
120 
121         public override Task OnConnectedAsync()
122 
123         {
124 
125             if (FirstConnected)
126 
127             {
128 
129                 //加锁,防止其它线程多次触发
130 
131                 lock (balanceLock)
132 
133                 {
134 
135                     if (FirstConnected)
136 
137                     {
138 
139                         //在线状态全设置成离线(记录数据保存在MSSQL)
140 
141                         online.SetOfflineOfAll();
142 
143                         FirstConnected = false;
144 
145                     }
146 
147                 }
148 
149             }
150 
151             //设置在线状态,更改数据库中在线状态字段,1=在线,0=离线
152 
153             SetOnlineStatus(Context.ConnectionId, 1);
154 
155             //向管理员推送用户在线信息
156 
157             SendMessageAdmin();
158 
159             if(Context.UserIdentifier=="admin")
160 
161             {
162 
163                 //从Redis中获取未推送消息(管理员离线未接收)
164 
165                 var listRange = RedisHelper.ListRange<string>(Context.UserIdentifier) as List<string>;
166 
167                 //遍历数据逐条推送
168 
169                 foreach (var item in listRange)
170 
171                 {
172 
173                     Clients.User("admin").SendAsync("UploadFilesMessage","", item);
174 
175                 }
176 
177             }
178 
179             return base.OnConnectedAsync();
180 
181         }
182 
183  
184 
185         /// <summary>
186 
187         /// 连接断开触发
188 
189         /// </summary>
190 
191         /// <param name="exception"></param>
192 
193         /// <returns></returns>
194 
195         public override Task OnDisconnectedAsync(Exception exception)
196 
197         {
198 
199             SetOnlineStatus(Context.ConnectionId);
200 
201             SendMessageAdmin(0);
202 
203             return base.OnDisconnectedAsync(exception);
204 
205         }
206 
207  
208 
209         /// <summary>
210 
211         /// 加入组
212 
213         /// </summary>
214 
215         /// <param name="groupName"></param>
216 
217         /// <returns></returns>
218 
219         public async Task AddToGroup(string groupName)
220 
221         {
222 
223             await Groups.AddToGroupAsync(Context.ConnectionId, groupName);
224 
225  
226 
227             await Clients.Group(groupName).SendAsync("Send", $"{Context.ConnectionId} has joined the group {groupName}.");
228 
229         }
230 
231  
232 
233         /// <summary>
234 
235         /// 从组中删除
236 
237         /// </summary>
238 
239         /// <param name="groupName"></param>
240 
241         /// <returns></returns>
242 
243         public async Task RemoveFromGroup(string groupName)
244 
245         {
246 
247             await Groups.RemoveFromGroupAsync(Context.ConnectionId, groupName);
248 
249  
250 
251             await Clients.Group(groupName).SendAsync("Send", $"{Context.ConnectionId} has left the group {groupName}.");
252 
253         }
254 
255  
256 
257         /// <summary>
258 
259         /// 向管理员推送信息
260 
261         /// </summary>
262 
263         public async void SendMessageAdmin(int status = 1)
264 
265         {
266 
267             if (Context.UserIdentifier == "admin") return;
268 
269             var name = Context.User.FindFirstValue(ClaimTypes.GivenName);
270 
271             var statusstr = status == 1 ? "上线" : "下线";
272 
273             await Clients.User("admin").SendAsync("DynamicMessage", status, $"用户 {name} {statusstr}啦!");
274 
275         }
276 
277  
278 
279         /// <summary>
280 
281         /// 设置在线状态(保存至数据库)
282 
283         /// </summary>
284 
285         /// <param name="conneciionId"></param>
286 
287         /// <param name="status"></param>
288 
289         public void SetOnlineStatus(string conneciionId, int status = 0)
290 
291         {
292 
293             var appUser = commonUser.AppUserModebyLoginName(Context.UserIdentifier);
294 
295             online.SetOnlineStatus(appUser, conneciionId, status);
296 
297         }
298 
299  
300 
301         /// <summary>
302 
303         /// 客户端调用,表示信息已接收,数据从Redis中删除
304 
305         /// </summary>
306 
307         /// <param name="message"></param>
308 
309         public void CallBlack(string message)
310 
311         {
312 
313             RedisHelper.ListRemove("admin",message);
314 
315         }
316 
317  
318 
319     }
320 
321 }

前端

  1 //需要引用
  2 
  3 //提示框插件
  4 
  5 <script src="~/lib/toastr-2.1.4/toastr.min.js"></script>
  6 
  7 //signalr必须
  8 
  9 <script src="~/lib/signalr/dist/browser/signalr.js"></script>
 10 
 11  
 12 
 13 "use strict";
 14 
 15 let connection = new signalR.HubConnectionBuilder().withUrl("/chatHub").build();
 16 
 17  
 18 
 19 //记录重连次数
 20 
 21 let number = 0;
 22 
 23  
 24 
 25 (function () { initializeToastr(); connectionStar();})();
 26 
 27  
 28 
 29 //初始化toastr插件属性
 30 
 31 function initializeToastr() {
 32 
 33     toastr.options = {
 34 
 35         progressBar: true,
 36 
 37         closeButton: false,
 38 
 39         debug: false,
 40 
 41         positionClass: "toast-bottom-right",
 42 
 43         onclick: null,
 44 
 45         showDuration: "300",
 46 
 47         hideDuration: "1000",
 48 
 49         timeOut: 5000,
 50 
 51         extendedTimeOut: 5000,
 52 
 53         showEasing: "swing",
 54 
 55         hideEasing: "linear",
 56 
 57         showMethod: "fadeIn",
 58 
 59         hideMethod: "fadeOut"
 60 
 61     };
 62 
 63 }
 64 
 65  
 66 
 67 function connectionStar() {
 68 
 69     initializeToastr();
 70 
 71     //开始连接
 72 
 73     connection.start().then(function () {
 74 
 75         if (number > 0) {
 76 
 77             //弹出提示框
 78 
 79             toastr.success("连接成功!");
 80 
 81             //连接成功,重置重连次数
 82 
 83             number = 0;
 84 
 85         }
 86 
 87     }).catch(function (err) {
 88 
 89         toastr.error("连接断开,正在重新连接(" + number + ")......");
 90 
 91         
 92 
 93         number++;
 94 
 95         //同步方法,等待执行完成
 96 
 97         setTimeout(() => connectionStar(), 5000);
 98 
 99     });
100 
101 }
102 
103  
104 
105 //接收推送消息
106 
107 //function内参数,取决于后台中[await Clients.User("").SendAsync(method,status,message)]参数个数
108 
109 //参数顺序一一对应
110 
111 connection.on("DynamicMessage", function (status, message) {
112 
113     initializeToastr();
114 
115     //status 1=在线,2=离线
116 
117     if (status === 1)
118 
119         toastr.info(message);
120 
121     else
122 
123         toastr.info("<dev style='color:#C7C7C7'>" + message + "</dev>");
124 
125     //获取iframe对象
126 
127     let iframe = document.getElementById("J_iframe").contentWindow;
128 
129     //获取iframe打开的Url
130 
131     let url = iframe.location.href;
132 
133     //判断iframe打开的是否是OnlineUsers页面
134 
135     if (url.indexOf("OnlineUsers") >= 0)
136 
137         iframe.clientAjax();
138 
139 });
140 
141  
142 
143 //接收推送消息
144 
145 connection.on("UploadFilesMessage", function (userId, message) {
146 
147     toastr.options.closeButton = true;
148 
149     toastr.options.timeOut = 20000;
150 
151     toastr.info(message);
152 
153     
154 
155     //想服务器推送消息,告知服务器消息已接收,"CallBlack"表示后台函数名
156 
157     connection.invoke("CallBlack", message).catch(function (err) {
158 
159         return toastr.error(err.toString());
160 
161     });
162 
163 });
164 
165  
166 
167 //连接断开触发
168 
169 connection.onclose(function () {
170 
171     //重新连接
172 
173     setTimeout(() => connectionStar(), 5000);
174 
175 });
176 
177  
178 
179 signalR主要方法
180 
181 JS
182 
183 let connection = new signalR.HubConnectionBuilder().withUrl("/chatHub").build();
184 
185 //连接
186 
187 connection.start().then(function () {
188 
189     //连接成功操作
190 
191     ......
192 
193 }).catch(function (err) {
194 
195     //连接失败操作
196 
197     ......
198 
199 });
200 
201 //接收推送
202 
203 connection.on("method", function (userId, message) {
204 
205     ......
206 
207 });
208 
209 //发送消息
210 
211 connection.invoke("method", message).catch(function (err) {
212 
213     //发送失败操作
214 
215     ......
216 
217 });
218 
219 //断开
220 
221 connection.onclose(function () {
222 
223     ......
224 
225 });

后台调用

 1 /// <summary>
 2 
 3 /// 连接触发
 4 
 5 /// </summary>
 6 
 7 /// <returns></returns>
 8 
 9 public override Task OnConnectedAsync()
10 
11 {
12 
13  
14 
15 }
16 
17 /// <summary>
18 
19 /// 连接断开触发
20 
21 /// </summary>
22 
23 /// <param name="exception"></param>
24 
25 /// <returns></returns>
26 
27 public override Task OnDisconnectedAsync(Exception exception)
28 
29 {
30 
31  
32 
33 }
34 
35 //消息推送
36 
37 await Clients.User("").SendAsync(method,status,message);
38 
39  
40 
41 其它类调用需要使用到注入
42 
43 public void Test([FromServices]IHubContext<ChatHub> hubContext)
44 
45 {
46 
47     hubContext.Clients.User(userId)
48 
49     .SendAsync(method, arg1, arg2);
50 
51 }

 

posted @ 2022-04-17 22:46  一事冇诚  阅读(1622)  评论(0编辑  收藏  举报