SignalR 持久鏈接

using System;
using System.Collections.Generic;
using System.Configuration;
using System.Linq;
using System.Threading;
using Microsoft.AspNet.SignalR;
using Microsoft.AspNet.SignalR.Transports;
using MY.BllModel;
using Newtonsoft.Json;
using Task = System.Threading.Tasks.Task;
using MY.Logging;
using MY.Utility;

namespace SignalR.Persistent
{
    /// <summary>
    /// 持久連接
    /// </summary>
    public partial class CharPersistent : PersistentConnection
    {
        //log類聲明爲局部靜態是爲性能考慮
        private static readonly LogHelper LogHelper = new LogHelper("SignalR.Persistent.CharPersistent");
        protected static SyncList<DeviceOnlineModel> UserModelList = new SyncList<DeviceOnlineModel>();

        /// <summary>
        /// 真實鏈接數量
        /// </summary>
        protected static int ConnectionsCount = 0;

        /// <summary>
        /// 接受到消息
        /// </summary>
        protected override async Task OnReceived(IRequest request, string connectionId, string data)
        {
            try
            {
                if (string.IsNullOrEmpty(data))
                {
                    throw new Exception("請求參數不能爲空");
                }

                var json = JsonConvert.DeserializeObject<Dictionary<string, object>>(data);
                if (!json.ContainsKey("type") || !json.ContainsKey("text"))
                {

                    throw new Exception("參數{type,text}不能爲空");
                }

                switch (json["type"].ToString().ToLower())
                {
                    case "online": //設備、web上線
                        await Online(request, connectionId, json["text"].ToString());
                        break;
                    case "ng": //設備、web指令接收
                        await MsgForwarding(connectionId, data);
                        if (json["text"].ToString().ToLower() == "getall")
                        {
                            LogHelper.DebugAsync("設備返回getall時間:" + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss fff"));
                        }

                        break;
                    case "onlineline": //獲得在線列表
                        Connection.SendToWeb(connectionId,
                            new {count = ConnectionsCount, list = UserModelList}.ToJson());
                        break;
                    case "sendmsg": //中轉服務器發送消息
                        ServiceSendMsg(json["userid"].ToString(), json["text"].ToString());
                        break;
                    case "appexceptionlog": //應用異常日誌
                        AddException(json["text"].ToString());
                        break;
                    case "recovered": //找回設備
                    case "notice": //通知回覆
                    case "getbluetooth": //取的藍牙數據
                    case "getappblacklist": //取的應用黑名單數據
                    case "getphonebook": //取的電話簿
                    case "removeapp": //刪除app
                        if (json["result"].ToString() == "1")
                        {
                            HandlePushEnd(json["text"].ToString());
                            LogHelper.DebugAsync(string.Format("特殊推送收到成功回覆,回覆類型:{0},json:{1}",
                                json["type"].ToString().ToLower(), data));
                        }
                        else
                        {
                            LogHelper.DebugAsync(string.Format("特殊推送收到失敗回覆,回覆類型:{0},json:{1}",
                                json["type"].ToString().ToLower(), data));
                        }

                        break;
                    default:
                        LogHelper.DebugAsync(string.Format("服務器接收到消息【{0}】,消息內容爲{1}", connectionId, data));
                        break;
                }
            }
            catch (Exception ex)
            {
                LogHelper.ErrorAsync("接收消息異常:" + (ex.InnerException != null ? ex.InnerException.Message : ex.Message));
                //錯誤指令返回
                Connection.SendErrMsg(connectionId, ex.Message);
            }
        }


        /// <summary>
        /// 用戶發送消息轉發處理
        /// </summary>
        /// <param name="userid"></param>
        /// <param name="msg"></param>
        private void ServiceSendMsg(string userid, string msg)
        {
            if (string.IsNullOrEmpty(userid))
            {
                return;
            }

            userid = Uri.EscapeDataString(userid);
            var entity = UserModelList.FirstOrDefaultV(q => q.UserId == userid && q.UserType == (int) UserType.AppUser);
            if (entity != null)
            {
                //指定用戶發送消息
                Connection.Send(entity.UserConnerctionId, msg);
            }

            LogHelper.DebugAsync(string.Format("服務推送消息給設備用戶【{0}】,消息內容爲{1}", userid, msg));
        }


        /// <summary>
        /// 上線
        /// </summary>
        /// <param name="request"></param>
        /// <param name="connectionId"></param>
        /// <param name="text"></param>
        private async Task Online(IRequest request, string connectionId, string text = "")
        {
            try
            {
                //獲得用戶信息
                if (string.IsNullOrEmpty(text))
                {
                    text = request.QueryString["userid"];
                    if (string.IsNullOrEmpty(text))
                    {
                        return;
                    }
                }

                if (string.IsNullOrEmpty(text))
                {
                    throw new Exception("參數{text}不能爲空");
                }

                var texts = text.Split('|');
                if (texts.Length < 2)
                {
                    throw new Exception("參數{text}異常:{\"type\":\"online\",\"text\":\"imei|usertype|sign|timestamp\"}");
                }

                var userid = texts[0]; //用戶
                var usertype = 0;
                if (!int.TryParse(texts[1], out usertype))
                {
                    throw new Exception(
                        "參數{text}異常:{\"type\":\"online\",\"text\":\"imei|usertype|sign|timestamp\"},usertype參數異常");
                }

                //存儲用戶
                var model = UserModelList.FirstOrDefaultV(q => q.UserConnerctionId == connectionId);
                if (model == null)
                {
                    userid = Uri.EscapeDataString(userid);
                    UserModelList.Add(new DeviceOnlineModel()
                        {UserConnerctionId = connectionId, UserId = userid, UserType = usertype});
                }

                //web上線
                if (usertype == (int) UserType.SysWebUser)
                {
                    //驗證請求地址是否合法
                    var hosts = ConfigurationManager.AppSettings["SignalRClientWebHost"];
                    if (!string.IsNullOrEmpty(hosts))
                    {
                        var arrHost = hosts.Split(',');
                        var origin = request.Headers["Origin"];
                        //非法地址直接斷開
                        if (!arrHost.Contains(origin))
                        {
                            LogHelper.ErrorAsync("非法連接,請求來源:" + request.Headers.ToJson() + ",連接數據:" + text);
                            await ServiceDisconnect(connectionId);
                            return;
                        }
                    }


                    //獲得要發送的鏈接id列表
                    var sendEntity = GetRrelatedSendList(connectionId).FirstOrDefault();
                    if (sendEntity != null)
                    {
                        //記錄日誌
                        LogHelper.DebugAsync("WEB用戶getall時間:" + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss fff"));
                        //推送獲取設備信息指令
                        await Task.Run(() => Connection.SendToDevice(sendEntity.UserConnerctionId,
                            JsonConvert.SerializeObject(new {type = "ng", text = "getall",})));

                        //告知web該設備在線
                        //await Task.Run(() => Connection.SendToWeb(connectionId, "Online"));
                    }
                    else
                    {
                        //告知web該設備不在線
                        await Task.Run(() => Connection.SendToWeb(connectionId, "NoOnline"));
                    }

                    //記錄日誌
                    LogHelper.DebugAsync("WEB用戶【" + Uri.UnescapeDataString(userid) + "】上線了");
                }
                //設備上線
                else
                {
                    //驗證請求是否合法
                    if (texts.Length != 4)
                    {
                        throw new Exception(
                            "參數{text}異常:{\"type\":\"online\",\"text\":\"imei|usertype|sign|timestamp\"}");
                    }

                    //檢測是否合法
                    var signalRKey = ConfigurationManager.AppSettings["SignalRKey"];
                    if (signalRKey != "")
                    {
                        var sign = texts[2];
                        var timestamp = texts[3];
                        var sign2 = MY.Utility.Encryption.EncryptMd5($"{userid}|{usertype}|{timestamp}|{signalRKey}");
                        if (!sign.Equals(sign2, StringComparison.OrdinalIgnoreCase))
                        {
                            LogHelper.ErrorAsync("非法連接 ,連接數據:" + text);
                            await ServiceDisconnect(connectionId);
                            return;
                        }
                    }

                    //存在網站用戶登陸
                    bool onlineCnt =
                        UserModelList.AnyV(o => o.UserId == userid && o.UserType == (int) UserType.SysWebUser);

                    if (onlineCnt)
                    {
                        //推送獲取設備信息指令
                        await Task.Run(() => Connection.SendToDevice(connectionId,
                            JsonConvert.SerializeObject(new {type = "ng", text = "getall",})));
                    }

                    //記錄日誌
                    LogHelper.DebugAsync("設備用戶【" + Uri.UnescapeDataString(text) + "】上線了");

                    //同步設備在線情況
                    SyncDeviceOnlineSituation();

                    //寫入設備上線記錄
                    AddDeviceConnectLog(userid, connectionId, 1, "設備上線");
                }
            }
            catch (Exception e)
            {
                LogHelper.ErrorAsync("連接上線異常【" + text + "】:" +
                                     (e.InnerException != null ? e.InnerException.Message : e.Message));
                LogHelper.ErrorAsync("異常堆棧:" + e.ToJson());

                //錯誤指令返回
                Connection.SendErrMsg(connectionId, e.Message);
                ServiceDisconnect(connectionId, false);
            }
        }



        /// <summary>
        /// 連接斷開 
        /// </summary>
        protected override async Task OnDisconnected(IRequest request, string connectionId, bool stopCalled)
        {
            Interlocked.Decrement(ref ConnectionsCount);
            try
            {
                DeviceOnlineModel model = UserModelList.FirstOrDefaultV(q => q.UserConnerctionId == connectionId);


                if (model != null)
                {
                    //設備離線
                    if (model.UserType == (int) UserType.AppUser)
                    {
                        var sendEntitys = GetRrelatedSendList(connectionId);
                        if (sendEntitys != null)
                        {
                            foreach (var sendEntity in sendEntitys)
                            {
                                List<DeviceOnlineModel> onlineList = UserModelList.WhereV(o =>
                                    o.UserId == model.UserId && o.UserType == (int) UserType.AppUser).ToList();

                                if (onlineList.Count() == 1)
                                {
                                    //推送設備離線
                                    await Task.Run(() =>
                                        Connection.SendToWeb(sendEntity.UserConnerctionId, "NoOnline"));
                                }
                            }
                        }

                        LogHelper.DebugAsync("設備用戶【" + Uri.UnescapeDataString(model.UserId + "|" + model.UserType) +
                                             "】下線了");
#pragma warning disable 4014

                        //同步設備在線情況
                        SyncDeviceOnlineSituation();

                        //寫入設備下線記錄
                        AddDeviceConnectLog(model.UserId, connectionId, 2, "設備下線");
#pragma warning restore 4014
                    }
                    else
                    {
                        LogHelper.DebugAsync("WEB用戶【" + Uri.UnescapeDataString(model.UserId + "|" + model.UserType) +
                                             "】下線了");
                    }


                    UserModelList.Remove(model);

                }
            }
            catch (Exception e)
            {
                LogHelper.ErrorAsync("連接斷開異常【" + connectionId + "】:" +
                                     (e.InnerException != null ? e.InnerException.Message : e.Message));
                LogHelper.ErrorAsync("異常堆棧:" + e.ToJson());
            }

            //默認調用
            await base.OnDisconnected(request, connectionId, stopCalled);
        }


        /// <summary>
        /// 連接創建
        /// </summary>
        protected override async Task OnConnected(IRequest request, string connectionId)
        {
            Interlocked.Increment(ref ConnectionsCount);
            //特定內部不需要上線直接發消息
            if (request.QueryString["inner"] + "" == "yes")
            {
                await base.OnConnected(request, connectionId);
                return;
            }

            await Online(request, connectionId);
            await base.OnConnected(request, connectionId);
        }


        /// <summary>
        /// 重新連接
        /// </summary>
        /// <param name="request"></param>
        /// <param name="connectionId"></param>
        /// <returns></returns>
        protected override async Task OnReconnected(IRequest request, string connectionId)
        {
            //ConnectionsCount++;
            await Online(request, connectionId);
            await base.OnReconnected(request, connectionId);
        }


        /// <summary>
        /// 消息轉發,通過當前消息用戶鏈接id找到對應的用戶鏈接id
        /// </summary>
        /// <param name="userConnerctionId"></param>
        /// <param name="data"></param>
        private async Task MsgForwarding(string userConnerctionId, string data)
        {
            if (string.IsNullOrEmpty(userConnerctionId))
            {
                return;
            }

            //獲得要發送的鏈接id列表
            var sendEntitys = GetRrelatedSendList(userConnerctionId);
            if (sendEntitys != null)
            {
                foreach (var model in sendEntitys)
                {
                    if (model != null)
                    {
                        //指定用戶發送消息
                        await Connection.Send(model.UserConnerctionId, data);

                        LogHelper.DebugAsync($"服務器轉發消息給用戶:{model.UserId}|{model.UserType},內容爲:{data}");
                    }
                }
            }

            //記錄用戶記錄
            DeviceOnlineModel entity = UserModelList.FirstOrDefaultV(o => o.UserConnerctionId == userConnerctionId);


            if (entity != null)
            {
                //指令發送成功後回覆發送端發送成功
                if (entity.UserType == (int) UserType.SysWebUser)
                {
                    var dic = JsonConvert.DeserializeObject<Dictionary<string, object>>(data);
                    if (dic["text"].Equals("restart")
                        || dic["text"].Equals("shutdown")
                        || dic["text"].Equals("resumedefault"))
                    {
                        await Connection.Send(entity.UserConnerctionId, "MainSendOK");
                    }
                }

                LogHelper.DebugAsync("服務器接收到【" + (entity.UserType == (int) UserType.SysWebUser ? "WEB" : "設備") +
                                     "】用戶【" + entity.UserId + "】,消息內容爲:" + data);
            }
        }



        /// <summary>
        /// 獲得發送連接id列表
        /// </summary>
        /// <param name="userConnerctionId"></param>
        /// <returns></returns>
        public List<DeviceOnlineModel> GetRrelatedSendList(string userConnerctionId)
        {

            //發送消息的用戶
            var entity = UserModelList.FirstOrDefaultV(q => q.UserConnerctionId == userConnerctionId);
            if (entity != null)
            {
                var usertype = entity.UserType == (int) UserType.AppUser
                    ? (int) UserType.SysWebUser
                    : (int) UserType.AppUser;
                //要推送消息的用戶
                var sendEntitys = UserModelList.WhereV(q => q.UserId == entity.UserId && q.UserType == usertype)
                    .ToList();
                return sendEntitys;
            }

            return null;
        }


        /// <summary>
        /// 服務器強制斷開連接
        /// </summary>
        /// <param name="connectionId"></param>
        /// <param name="isSendErrMsg"></param>
        private async Task ServiceDisconnect(string connectionId, bool isSendErrMsg = true)
        {
            await GlobalHost.DependencyResolver.Resolve<ITransportHeartbeat>().GetConnections()
                .First(o => o.ConnectionId == connectionId).Disconnect();
            if (isSendErrMsg)
            {
                //錯誤指令返回
                Connection.SendErrMsg(connectionId, "非法連接,強制斷開");
            }
        }

    }

}

 

using System;
  using System.Collections.Generic;
  using System.Configuration;
  using System.Linq;
  using System.Threading;
  using Microsoft.AspNet.SignalR;
  using Microsoft.AspNet.SignalR.Transports;
  using MY.BllModel;
  using Newtonsoft.Json;
  using Task = System.Threading.Tasks.Task;
  using MY.Logging;
  using MY.Utility;
   
  namespace SignalR.Persistent
  {
  /// <summary>
  /// 持久連接
  /// </summary>
  public partial class CharPersistent : PersistentConnection
  {
  //log類聲明爲局部靜態是爲性能考慮
  private static readonly LogHelper LogHelper = new LogHelper("SignalR.Persistent.CharPersistent");
  protected static SyncList<DeviceOnlineModel> UserModelList = new SyncList<DeviceOnlineModel>();
   
  /// <summary>
  /// 真實鏈接數量
  /// </summary>
  protected static int ConnectionsCount = 0;
   
  /// <summary>
  /// 接受到消息
  /// </summary>
  protected override async Task OnReceived(IRequest request, string connectionId, string data)
  {
  try
  {
  if (string.IsNullOrEmpty(data))
  {
  throw new Exception("請求參數不能爲空");
  }
   
  var json = JsonConvert.DeserializeObject<Dictionary<string, object>>(data);
  if (!json.ContainsKey("type") || !json.ContainsKey("text"))
  {
   
  throw new Exception("參數{type,text}不能爲空");
  }
   
  switch (json["type"].ToString().ToLower())
  {
  case "online": //設備、web上線
  await Online(request, connectionId, json["text"].ToString());
  break;
  case "ng": //設備、web指令接收
  await MsgForwarding(connectionId, data);
  if (json["text"].ToString().ToLower() == "getall")
  {
  LogHelper.DebugAsync("設備返回getall時間:" + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss fff"));
  }
   
  break;
  case "onlineline": //獲得在線列表
  Connection.SendToWeb(connectionId,
  new {count = ConnectionsCount, list = UserModelList}.ToJson());
  break;
  case "sendmsg": //中轉服務器發送消息
  ServiceSendMsg(json["userid"].ToString(), json["text"].ToString());
  break;
  case "appexceptionlog": //應用異常日誌
  AddException(json["text"].ToString());
  break;
  case "recovered": //找回設備
  case "notice": //通知回覆
  case "getbluetooth": //取的藍牙數據
  case "getappblacklist": //取的應用黑名單數據
  case "getphonebook": //取的電話簿
  case "removeapp": //刪除app
  if (json["result"].ToString() == "1")
  {
  HandlePushEnd(json["text"].ToString());
  LogHelper.DebugAsync(string.Format("特殊推送收到成功回覆,回覆類型:{0},json:{1}",
  json["type"].ToString().ToLower(), data));
  }
  else
  {
  LogHelper.DebugAsync(string.Format("特殊推送收到失敗回覆,回覆類型:{0},json:{1}",
  json["type"].ToString().ToLower(), data));
  }
   
  break;
  default:
  LogHelper.DebugAsync(string.Format("服務器接收到消息【{0}】,消息內容爲{1}", connectionId, data));
  break;
  }
  }
  catch (Exception ex)
  {
  LogHelper.ErrorAsync("接收消息異常:" + (ex.InnerException != null ? ex.InnerException.Message : ex.Message));
  //錯誤指令返回
  Connection.SendErrMsg(connectionId, ex.Message);
  }
  }
   
   
  /// <summary>
  /// 用戶發送消息轉發處理
  /// </summary>
  /// <param name="userid"></param>
  /// <param name="msg"></param>
  private void ServiceSendMsg(string userid, string msg)
  {
  if (string.IsNullOrEmpty(userid))
  {
  return;
  }
   
  userid = Uri.EscapeDataString(userid);
  var entity = UserModelList.FirstOrDefaultV(q => q.UserId == userid && q.UserType == (int) UserType.AppUser);
  if (entity != null)
  {
  //指定用戶發送消息
  Connection.Send(entity.UserConnerctionId, msg);
  }
   
  LogHelper.DebugAsync(string.Format("服務推送消息給設備用戶【{0}】,消息內容爲{1}", userid, msg));
  }
   
   
  /// <summary>
  /// 上線
  /// </summary>
  /// <param name="request"></param>
  /// <param name="connectionId"></param>
  /// <param name="text"></param>
  private async Task Online(IRequest request, string connectionId, string text = "")
  {
  try
  {
  //獲得用戶信息
  if (string.IsNullOrEmpty(text))
  {
  text = request.QueryString["userid"];
  if (string.IsNullOrEmpty(text))
  {
  return;
  }
  }
   
  if (string.IsNullOrEmpty(text))
  {
  throw new Exception("參數{text}不能爲空");
  }
   
  var texts = text.Split('|');
  if (texts.Length < 2)
  {
  throw new Exception("參數{text}異常:{\"type\":\"online\",\"text\":\"imei|usertype|sign|timestamp\"}");
  }
   
  var userid = texts[0]; //用戶
  var usertype = 0;
  if (!int.TryParse(texts[1], out usertype))
  {
  throw new Exception(
  "參數{text}異常:{\"type\":\"online\",\"text\":\"imei|usertype|sign|timestamp\"},usertype參數異常");
  }
   
  //存儲用戶
  var model = UserModelList.FirstOrDefaultV(q => q.UserConnerctionId == connectionId);
  if (model == null)
  {
  userid = Uri.EscapeDataString(userid);
  UserModelList.Add(new DeviceOnlineModel()
  {UserConnerctionId = connectionId, UserId = userid, UserType = usertype});
  }
   
  //web上線
  if (usertype == (int) UserType.SysWebUser)
  {
  //驗證請求地址是否合法
  var hosts = ConfigurationManager.AppSettings["SignalRClientWebHost"];
  if (!string.IsNullOrEmpty(hosts))
  {
  var arrHost = hosts.Split(',');
  var origin = request.Headers["Origin"];
  //非法地址直接斷開
  if (!arrHost.Contains(origin))
  {
  LogHelper.ErrorAsync("非法連接,請求來源:" + request.Headers.ToJson() + ",連接數據:" + text);
  await ServiceDisconnect(connectionId);
  return;
  }
  }
   
   
  //獲得要發送的鏈接id列表
  var sendEntity = GetRrelatedSendList(connectionId).FirstOrDefault();
  if (sendEntity != null)
  {
  //記錄日誌
  LogHelper.DebugAsync("WEB用戶getall時間:" + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss fff"));
  //推送獲取設備信息指令
  await Task.Run(() => Connection.SendToDevice(sendEntity.UserConnerctionId,
  JsonConvert.SerializeObject(new {type = "ng", text = "getall",})));
   
  //告知web該設備在線
  //await Task.Run(() => Connection.SendToWeb(connectionId, "Online"));
  }
  else
  {
  //告知web該設備不在線
  await Task.Run(() => Connection.SendToWeb(connectionId, "NoOnline"));
  }
   
  //記錄日誌
  LogHelper.DebugAsync("WEB用戶【" + Uri.UnescapeDataString(userid) + "】上線了");
  }
  //設備上線
  else
  {
  //驗證請求是否合法
  if (texts.Length != 4)
  {
  throw new Exception(
  "參數{text}異常:{\"type\":\"online\",\"text\":\"imei|usertype|sign|timestamp\"}");
  }
   
  //檢測是否合法
  var signalRKey = ConfigurationManager.AppSettings["SignalRKey"];
  if (signalRKey != "")
  {
  var sign = texts[2];
  var timestamp = texts[3];
  var sign2 = MY.Utility.Encryption.EncryptMd5($"{userid}|{usertype}|{timestamp}|{signalRKey}");
  if (!sign.Equals(sign2, StringComparison.OrdinalIgnoreCase))
  {
  LogHelper.ErrorAsync("非法連接 ,連接數據:" + text);
  await ServiceDisconnect(connectionId);
  return;
  }
  }
   
  //存在網站用戶登陸
  bool onlineCnt =
  UserModelList.AnyV(o => o.UserId == userid && o.UserType == (int) UserType.SysWebUser);
   
  if (onlineCnt)
  {
  //推送獲取設備信息指令
  await Task.Run(() => Connection.SendToDevice(connectionId,
  JsonConvert.SerializeObject(new {type = "ng", text = "getall",})));
  }
   
  //記錄日誌
  LogHelper.DebugAsync("設備用戶【" + Uri.UnescapeDataString(text) + "】上線了");
   
  //同步設備在線情況
  SyncDeviceOnlineSituation();
   
  //寫入設備上線記錄
  AddDeviceConnectLog(userid, connectionId, 1, "設備上線");
  }
  }
  catch (Exception e)
  {
  LogHelper.ErrorAsync("連接上線異常【" + text + "】:" +
  (e.InnerException != null ? e.InnerException.Message : e.Message));
  LogHelper.ErrorAsync("異常堆棧:" + e.ToJson());
   
  //錯誤指令返回
  Connection.SendErrMsg(connectionId, e.Message);
  ServiceDisconnect(connectionId, false);
  }
  }
   
   
   
  /// <summary>
  /// 連接斷開
  /// </summary>
  protected override async Task OnDisconnected(IRequest request, string connectionId, bool stopCalled)
  {
  Interlocked.Decrement(ref ConnectionsCount);
  try
  {
  DeviceOnlineModel model = UserModelList.FirstOrDefaultV(q => q.UserConnerctionId == connectionId);
   
   
  if (model != null)
  {
  //設備離線
  if (model.UserType == (int) UserType.AppUser)
  {
  var sendEntitys = GetRrelatedSendList(connectionId);
  if (sendEntitys != null)
  {
  foreach (var sendEntity in sendEntitys)
  {
  List<DeviceOnlineModel> onlineList = UserModelList.WhereV(o =>
  o.UserId == model.UserId && o.UserType == (int) UserType.AppUser).ToList();
   
  if (onlineList.Count() == 1)
  {
  //推送設備離線
  await Task.Run(() =>
  Connection.SendToWeb(sendEntity.UserConnerctionId, "NoOnline"));
  }
  }
  }
   
  LogHelper.DebugAsync("設備用戶【" + Uri.UnescapeDataString(model.UserId + "|" + model.UserType) +
  "】下線了");
  #pragma warning disable 4014
   
  //同步設備在線情況
  SyncDeviceOnlineSituation();
   
  //寫入設備下線記錄
  AddDeviceConnectLog(model.UserId, connectionId, 2, "設備下線");
  #pragma warning restore 4014
  }
  else
  {
  LogHelper.DebugAsync("WEB用戶【" + Uri.UnescapeDataString(model.UserId + "|" + model.UserType) +
  "】下線了");
  }
   
   
  UserModelList.Remove(model);
   
  }
  }
  catch (Exception e)
  {
  LogHelper.ErrorAsync("連接斷開異常【" + connectionId + "】:" +
  (e.InnerException != null ? e.InnerException.Message : e.Message));
  LogHelper.ErrorAsync("異常堆棧:" + e.ToJson());
  }
   
  //默認調用
  await base.OnDisconnected(request, connectionId, stopCalled);
  }
   
   
  /// <summary>
  /// 連接創建
  /// </summary>
  protected override async Task OnConnected(IRequest request, string connectionId)
  {
  Interlocked.Increment(ref ConnectionsCount);
  //特定內部不需要上線直接發消息
  if (request.QueryString["inner"] + "" == "yes")
  {
  await base.OnConnected(request, connectionId);
  return;
  }
   
  await Online(request, connectionId);
  await base.OnConnected(request, connectionId);
  }
   
   
  /// <summary>
  /// 重新連接
  /// </summary>
  /// <param name="request"></param>
  /// <param name="connectionId"></param>
  /// <returns></returns>
  protected override async Task OnReconnected(IRequest request, string connectionId)
  {
  //ConnectionsCount++;
  await Online(request, connectionId);
  await base.OnReconnected(request, connectionId);
  }
   
   
  /// <summary>
  /// 消息轉發,通過當前消息用戶鏈接id找到對應的用戶鏈接id
  /// </summary>
  /// <param name="userConnerctionId"></param>
  /// <param name="data"></param>
  private async Task MsgForwarding(string userConnerctionId, string data)
  {
  if (string.IsNullOrEmpty(userConnerctionId))
  {
  return;
  }
   
  //獲得要發送的鏈接id列表
  var sendEntitys = GetRrelatedSendList(userConnerctionId);
  if (sendEntitys != null)
  {
  foreach (var model in sendEntitys)
  {
  if (model != null)
  {
  //指定用戶發送消息
  await Connection.Send(model.UserConnerctionId, data);
   
  LogHelper.DebugAsync($"服務器轉發消息給用戶:{model.UserId}|{model.UserType},內容爲:{data}");
  }
  }
  }
   
  //記錄用戶記錄
  DeviceOnlineModel entity = UserModelList.FirstOrDefaultV(o => o.UserConnerctionId == userConnerctionId);
   
   
  if (entity != null)
  {
  //指令發送成功後回覆發送端發送成功
  if (entity.UserType == (int) UserType.SysWebUser)
  {
  var dic = JsonConvert.DeserializeObject<Dictionary<string, object>>(data);
  if (dic["text"].Equals("restart")
  || dic["text"].Equals("shutdown")
  || dic["text"].Equals("resumedefault"))
  {
  await Connection.Send(entity.UserConnerctionId, "MainSendOK");
  }
  }
   
  LogHelper.DebugAsync("服務器接收到【" + (entity.UserType == (int) UserType.SysWebUser ? "WEB" : "設備") +
  "】用戶【" + entity.UserId + "】,消息內容爲:" + data);
  }
  }
   
   
   
  /// <summary>
  /// 獲得發送連接id列表
  /// </summary>
  /// <param name="userConnerctionId"></param>
  /// <returns></returns>
  public List<DeviceOnlineModel> GetRrelatedSendList(string userConnerctionId)
  {
   
  //發送消息的用戶
  var entity = UserModelList.FirstOrDefaultV(q => q.UserConnerctionId == userConnerctionId);
  if (entity != null)
  {
  var usertype = entity.UserType == (int) UserType.AppUser
  ? (int) UserType.SysWebUser
  : (int) UserType.AppUser;
  //要推送消息的用戶
  var sendEntitys = UserModelList.WhereV(q => q.UserId == entity.UserId && q.UserType == usertype)
  .ToList();
  return sendEntitys;
  }
   
  return null;
  }
   
   
  /// <summary>
  /// 服務器強制斷開連接
  /// </summary>
  /// <param name="connectionId"></param>
  /// <param name="isSendErrMsg"></param>
  private async Task ServiceDisconnect(string connectionId, bool isSendErrMsg = true)
  {
  await GlobalHost.DependencyResolver.Resolve<ITransportHeartbeat>().GetConnections()
  .First(o => o.ConnectionId == connectionId).Disconnect();
  if (isSendErrMsg)
  {
  //錯誤指令返回
  Connection.SendErrMsg(connectionId, "非法連接,強制斷開");
  }
  }
   
  }
   
  }
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章