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 }
本文来自博客园,作者:一事冇诚,转载请注明原文链接:https://www.cnblogs.com/ysmc/p/16147248.html