• 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 }
  • 相关阅读:
    java内部类与其他类变量之间的调用方式
    java线程数设置和系统cpu的关系
    IDEA设置方法自动显示参数提示
    (十)学生课程表查询
    (九)协处理器
    (八)filter的使用
    (七)多线程写入数据
    (六)mapreduce和Hbase集成
    (五)阅读推荐
    (四)region代码实现
  • 原文地址:https://www.cnblogs.com/ysmc/p/16147248.html
Copyright © 2020-2023  润新知