当前位置: 首页 > 工具软件 > SignalR > 使用案例 >

SignalR

骆磊
2023-12-01

SignalR官方简介

创建控制台应用程序启动SignalR服务

using Microsoft.AspNet.SignalR;
using Owin;
using Microsoft.Owin.Cors;
using Microsoft.Owin.Hosting;
using System;
using System.Reflection;
using System.Configuration;
using log4net;

namespace SignalRServer
{
    public class Startup
    {
        public static ILog log = LogManager.GetLogger("SignalR Server Log");
        /// <summary>
        /// 开启服务
        /// </summary>
        public static void Start()
        {
            //string SignalRURI = @"https://localhost:44342/";
            string SignalRURI = ConfigurationManager.AppSettings["SignalRServerUrl"].ToString().Trim();
            try
            {
                log4net.Config.XmlConfigurator.Configure();
                try
                {
                    using (WebApp.Start(SignalRURI, builder =>
                    {
                        builder.Map("/signalr", map =>
                        {
                            // Setup the cors middleware to run before SignalR.
                            // By default this will allow all origins. You can 
                            // configure the set of origins and/or http verbs by
                            // providing a cors options with a different policy.
                            map.UseCors(CorsOptions.AllowAll);
                            var hubConfiguration = new HubConfiguration
                            {
                                // You can enable JSONP by uncommenting line below.
                                // JSONP requests are insecure but some older browsers (and some
                                // versions of IE) require JSONP to work cross domain
                                EnableJSONP = true
                            };
                            // Run the SignalR pipeline. We're not using MapSignalR
                            // since this branch is already runs under the "/signalr"
                            // path.
                            map.RunSignalR(hubConfiguration);
                        });
                        builder.MapSignalR();

                    }))
                    {
                        Console.WriteLine("服务开启成功,运行在{0}", SignalRURI);
                        log.Info($"服务开启成功,运行在{SignalRURI}");
                        Console.ReadLine();
                    }
                }
                catch (TargetInvocationException)
                {
                    Console.WriteLine("服务开启失败. 已经有一个服务运行在{0}", SignalRURI);
                    log.Error($"服务开启失败. 已经有一个服务运行在{SignalRURI}");
                    Console.ReadLine();
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine("服务开启异常:{0}", ex.ToString());
                log.Error($"服务开启异常:{ex}");
                Console.ReadLine();
            }

        }
    }
}

using Microsoft.AspNet.SignalR;
using Microsoft.AspNet.SignalR.Hubs;
using System;
using System.Threading.Tasks;

namespace SignalRServer
{
    /// <summary>
    /// 即使通信服务(可供客户端调用的方法开头用小写)
    /// </summary>
    [HubName("ChatsHub")]
    public class Chats : Hub
    {
        #region 重载Hub方法
        /// <summary>
        /// 建立连接
        /// </summary>
        /// <returns></returns>
        public override Task OnConnected()
        {
            AddOnline();
            return base.OnConnected();
        }
        /// <summary>
        /// 断开连接
        /// </summary>
        /// <param name="stopCalled">是否是客户端主动断开:true是,false超时断开</param>
        /// <returns></returns>
        public override Task OnDisconnected(bool stopCalled)
        {
            RemoveOnline();
            return base.OnDisconnected(stopCalled);
        }
        /// <summary>
        /// 重新建立连接
        /// </summary>
        /// <returns></returns>
        public override Task OnReconnected()
        {
            AddOnline();
            return base.OnReconnected();
        }
        #endregion

        #region 私有方法
        /// <summary>
        /// 添加在线用户
        /// </summary>
        private void AddOnline()
        {
            string clientId = Context.ConnectionId;
            string userId = GetUserId();
            Groups.Add(clientId, userId);
            Console.WriteLine($"ClientId:{clientId} UserId:{userId} AddOnline");
            Startup.log.Info($"ClientId:{clientId} UserId:{userId} AddOnline");
        }
        /// <summary>
        /// 移除在线用户
        /// </summary>
        private void RemoveOnline()
        {
            string clientId = Context.ConnectionId;
            string userId = GetUserId();
            Groups.Remove(clientId, userId);
            Console.WriteLine($"ClientId:{clientId} UserId:{userId} RemoveOnline");
            Startup.log.Info($"ClientId:{clientId} UserId:{userId} RemoveOnline");
        }
        /// <summary>
        /// 获取登录用户Id
        /// </summary>
        /// <returns></returns>
        private string GetUserId()
        {
            string userId = "";
            if (Context.QueryString["UserId"] != null)
            {
                userId = Context.QueryString["UserId"];
            }
            return userId;
        }
        #endregion

        #region 客户端操作
        /// <summary>
        /// 根据接收方客户端id发送消息
        /// </summary>
        /// <param name="sendUserId">发送方Id</param>
        /// <param name="revUserId">接收方Id,多客户端Id相同则都收到信息</param>
        /// <param name="msg">消息</param>
        /// <param name="time">发送时间</param>
        /// <param name="isSysMsg">是否系统消息</param>
        public void SendMsgByUserId(string sendUserId, string revUserId, string msg, DateTime time, bool isSysMsg)
        {
            Clients.Group(revUserId).RevMsg(sendUserId, msg, time, isSysMsg);
            Console.WriteLine($"{time} isSysMsg:{isSysMsg} Id:{sendUserId} Send To Id:{revUserId} Msg:{msg}");
            Startup.log.Info($"{time} isSysMsg:{isSysMsg} Id:{sendUserId} Send To Id:{revUserId} Msg:{msg}");
        }
        /// <summary>
        /// 向所有客户端发送消息
        /// </summary>
        /// <param name="sendUserId">发送方Id</param>
        /// <param name="msg">消息</param>
        /// <param name="time">发送时间</param>
        /// <param name="isSysMsg">是否系统消息</param>
        public void SendMsgAll(string sendUserId, string msg, DateTime time, bool isSysMsg)
        {
            this.Clients.All.RevMsg(sendUserId, msg, time, isSysMsg);
            Console.WriteLine($"{time} isSysMsg:{isSysMsg} Id:{sendUserId} Send Msg:{msg}");
            Startup.log.Info($"{time} isSysMsg:{isSysMsg} Id:{sendUserId} Send Msg:{msg}");
        }
        #endregion
    }
}

客户端操作类封装

using Microsoft.AspNet.SignalR.Client;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace SignalRClientTest
{
    public class HubClient
    {
        public Action<string> ConnectionError;//连接异常委托
        public event EventHandler<RevMsgAllEventArgs> RevMsgAllEvent;//消息接收事件
        private readonly HubConnection hubConnection;
        private readonly IHubProxy hubProxy;
        public string UserId { get; set; }

        /// <summary>
        /// HubClient构造函数
        /// </summary>
        /// <param name="signalrUrl">SignalR服务地址</param>
        /// <param name="hubName">通信服务名称</param>
        /// <param name="queryString">通信客户端ID查询字符串,多客户端ID相同则同组获取信息</param>
        public HubClient(string signalrUrl, string hubName, string queryString)
        {
            hubConnection = new HubConnection(signalrUrl, new Dictionary<string, string>() { { "UserId", queryString } });
            hubProxy = hubConnection.CreateHubProxy(hubName);
            UserId = queryString;
            hubConnection.Error += (Exception) => { ConnectionError?.Invoke("HubConnection Fail. " + Exception.Message); };//连接异常   
        }

        /// <summary>
        /// 连接测试
        /// </summary>
        public bool StartTest()
        {
            try
            {
                this.hubConnection.Start().Wait();
                this.hubConnection.Dispose();//使用Stop()关闭连接在Start()和Stop()连续切换的时候可能异常
                return true;
            }
            catch (Exception ex)
            {
                ConnectionError?.Invoke("HubConnection Start Test Fail. " + ex.Message);//连接测试异常   
            }
            return false;
        }
        /// <summary>
        /// 开启连接
        /// </summary>
        public void Start()
        {
            if (this.hubConnection.State != ConnectionState.Connected)
            {
                if (StartTest())
                    hubConnection.Start();
            }
        }

        /// <summary>
        /// 关闭连接
        /// </summary>
        public void Stop()
        {
            if (this.hubConnection.State == ConnectionState.Connected)
                hubConnection.Dispose();//使用Stop()关闭连接在Start()和Stop()连续切换的时候可能异常
        }

        /// <summary>
        /// 调用hub方法
        /// </summary>
        /// <param name="methodName">SignalR服务方法</param>
        /// <param name="args">SignalR服务方法参数</param>
        public void CallMethod(string methodName, params object[] args)
        {
            if (this.hubConnection.State == ConnectionState.Connected)
                hubProxy.Invoke(methodName, args);
        }

        public void RevMsg()
        {
            this.hubProxy.On("RevMsg",
                  (string sendId, string msg, DateTime time, bool isSyaMsg) =>
                  {
                      RevMsgAllEvent?.Invoke(this, new RevMsgAllEventArgs(sendId, msg, time, isSyaMsg));
                  });
        }
    }

    public class RevMsgAllEventArgs : EventArgs
    {
        public RevMsgAllEventArgs(string sendId, string msg, DateTime time, bool isSyaMsg)
        {
            this.SendId = sendId;
            this.Msg = msg;
            this.Time = time;
            this.IsSysMsg = isSyaMsg;
        }
        public string SendId { get; private set; }
        public string Msg { get; private set; }
        public DateTime Time { get; private set; }
        public bool IsSysMsg { get; private set; }
    }
}

代码连接

 类似资料: