• 浅尝SignalR


    垂涎WebSocket已经很久了,终于有了学习的机会。

    对于ASP.NET,试着用了下Fleck,比较方便,但是问题多多,一个挂则全挂,没时间去研究。

    之后,找到了SignalR,看大神们的博客后感觉简单且好用。

    原理神马的,后面再来贴,先记录下Demo小激动一下。

    首先,创建一个MVC项目SignalRDemo。

    接着,引入SignalR:

    引用完成后,就可以看到解决方案中多了这些:

    而且,在》添加》新建项,中会看到这里多了SignalR,

     接下来我们创建一个SignalR永久连接类

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Threading.Tasks;
    using System.Web;
    using Microsoft.AspNet.SignalR;
    
    namespace SignalRDemo.SignalR
    {
        public class MySignalRConnection : PersistentConnection
        {
            protected override Task OnConnected(IRequest request, string connectionId)
            {
                return Connection.Send(connectionId, "Welcome!");
            }
    
            protected override Task OnReceived(IRequest request, string connectionId, string data)
            {
                return Connection.Broadcast(data);
            }
        }
    }

    可以看到,新建的SignalR永久性连接类继承了PersistentConnection类,并且重写了OnConnected和OnReceived方法。这两个方法一个是建立链接时触发,一个是客户端向服务器发消息时触发。

    #region 程序集 Microsoft.AspNet.SignalR.Core, Version=2.4.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35
    // ...packagesMicrosoft.AspNet.SignalR.Core.2.4.0lib
    et45Microsoft.AspNet.SignalR.Core.dll
    #endregion
    
    using System.Collections.Generic;
    using System.Diagnostics;
    using System.Threading.Tasks;
    using Microsoft.AspNet.SignalR.Hosting;
    using Microsoft.AspNet.SignalR.Infrastructure;
    using Microsoft.AspNet.SignalR.Messaging;
    using Microsoft.AspNet.SignalR.Tracing;
    using Microsoft.AspNet.SignalR.Transports;
    using Newtonsoft.Json;
    
    namespace Microsoft.AspNet.SignalR
    {
        //
        // 摘要:
        //     Represents a connection between client and server.
        public abstract class PersistentConnection
        {
            protected PersistentConnection();
    
            //
            // 摘要:
            //     Gets the Microsoft.AspNet.SignalR.IConnection for the Microsoft.AspNet.SignalR.PersistentConnection.
            public IConnection Connection { get; }
            //
            // 摘要:
            //     Gets the Microsoft.AspNet.SignalR.IConnectionGroupManager for the Microsoft.AspNet.SignalR.PersistentConnection.
            public IConnectionGroupManager Groups { get; }
            public IMemoryPool Pool { get; set; }
            protected IAckHandler AckHandler { get; }
            protected IPerformanceCounterManager Counters { get; }
            protected JsonSerializer JsonSerializer { get; }
            protected IMessageBus MessageBus { get; }
            protected IProtectedData ProtectedData { get; }
            protected virtual TraceSource Trace { get; }
            protected ITraceManager TraceManager { get; }
            protected ITransport Transport { get; }
            protected IUserIdProvider UserIdProvider { get; }
    
            public bool Authorize(IRequest request);
            public virtual void Initialize(IDependencyResolver resolver);
            //
            // 摘要:
            //     OWIN entry point.
            //
            // 参数:
            //   environment:
            public Task ProcessRequest(IDictionary<string, object> environment);
            //
            // 摘要:
            //     Handles all requests for Microsoft.AspNet.SignalR.PersistentConnections.
            //
            // 参数:
            //   context:
            //     The Microsoft.AspNet.SignalR.Hosting.HostContext for the current request.
            //
            // 返回结果:
            //     A System.Threading.Tasks.Task that completes when the Microsoft.AspNet.SignalR.PersistentConnection
            //     pipeline is complete.
            //
            // 异常:
            //   T:System.InvalidOperationException:
            //     Thrown if connection wasn't initialized. Thrown if the transport wasn't specified.
            //     Thrown if the connection id wasn't specified.
            public virtual Task ProcessRequest(HostContext context);
            //
            // 摘要:
            //     Called before every request and gives the user a authorize the user.
            //
            // 参数:
            //   request:
            //     The Microsoft.AspNet.SignalR.IRequest for the current connection.
            //
            // 返回结果:
            //     A boolean value that represents if the request is authorized.
            protected virtual bool AuthorizeRequest(IRequest request);
            //
            // 摘要:
            //     Returns the signals used in the Microsoft.AspNet.SignalR.PersistentConnection.
            //
            // 参数:
            //   userId:
            //     The user id for the current connection.
            //
            //   connectionId:
            //     The id of the incoming connection.
            //
            // 返回结果:
            //     The signals used for this Microsoft.AspNet.SignalR.PersistentConnection.
            protected virtual IList<string> GetSignals(string userId, string connectionId);
            //
            // 摘要:
            //     Called when a new connection is made.
            //
            // 参数:
            //   request:
            //     The Microsoft.AspNet.SignalR.IRequest for the current connection.
            //
            //   connectionId:
            //     The id of the connecting client.
            //
            // 返回结果:
            //     A System.Threading.Tasks.Task that completes when the connect operation is complete.
            protected virtual Task OnConnected(IRequest request, string connectionId);
            //
            // 摘要:
            //     Called when a connection disconnects gracefully or due to a timeout.
            //
            // 参数:
            //   request:
            //     The Microsoft.AspNet.SignalR.IRequest for the current connection.
            //
            //   connectionId:
            //     The id of the disconnected connection.
            //
            //   stopCalled:
            //     true, if stop was called on the client closing the connection gracefully; false,
            //     if the connection has been lost for longer than the Microsoft.AspNet.SignalR.Configuration.IConfigurationManager.DisconnectTimeout.
            //     Timeouts can occur in scaleout when clients reconnect with another server.
            //
            // 返回结果:
            //     A System.Threading.Tasks.Task that completes when the disconnect operation is
            //     complete.
            protected virtual Task OnDisconnected(IRequest request, string connectionId, bool stopCalled);
            //
            // 摘要:
            //     Called when data is received from a connection.
            //
            // 参数:
            //   request:
            //     The Microsoft.AspNet.SignalR.IRequest for the current connection.
            //
            //   connectionId:
            //     The id of the connection sending the data.
            //
            //   data:
            //     The payload sent to the connection.
            //
            // 返回结果:
            //     A System.Threading.Tasks.Task that completes when the receive operation is complete.
            protected virtual Task OnReceived(IRequest request, string connectionId, string data);
            //
            // 摘要:
            //     Called when a connection reconnects after a timeout.
            //
            // 参数:
            //   request:
            //     The Microsoft.AspNet.SignalR.IRequest for the current connection.
            //
            //   connectionId:
            //     The id of the re-connecting client.
            //
            // 返回结果:
            //     A System.Threading.Tasks.Task that completes when the re-connect operation is
            //     complete.
            protected virtual Task OnReconnected(IRequest request, string connectionId);
            //
            // 摘要:
            //     Called when a connection reconnects after a timeout to determine which groups
            //     should be rejoined.
            //
            // 参数:
            //   request:
            //     The Microsoft.AspNet.SignalR.IRequest for the current connection.
            //
            //   groups:
            //     The groups the calling connection claims to be part of.
            //
            //   connectionId:
            //     The id of the reconnecting client.
            //
            // 返回结果:
            //     A collection of group names that should be joined on reconnect
            protected virtual IList<string> OnRejoiningGroups(IRequest request, IList<string> groups, string connectionId);
            //
            // 摘要:
            //     Validates the connection token and extracts the connection ID from it.
            //
            // 参数:
            //   context:
            //     The Microsoft.AspNet.SignalR.Hosting.HostContext representing the request.
            //
            //   connectionToken:
            //     The connection token to validate.
            //
            //   connectionId:
            //     If this method returns true, this output parameter receives the connection ID
            //     contained within the token.
            //
            //   message:
            //     If this method returns false, this output parameter receives an error message
            //     to report.
            //
            //   statusCode:
            //     If this method returns false, this output parameter receives an HTTP status code
            //     to report.
            //
            // 返回结果:
            //     A boolean indicating if the connection token was valid.
            protected internal virtual bool TryGetConnectionId(HostContext context, string connectionToken, out string connectionId, out string message, out int statusCode);
        }
    }

    先不用MQ,就写个简单的List来存储链接吧

    namespace SignalRDemo.App_Start
    {
        public class AppHelper
        {
            private AppHelper()
            {
                ConnectionList = new List<string>();
            }
            public static List<string> ConnectionList { get; set; }
        }
    }

    修改MySignalRConnection类

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Threading.Tasks;
    using System.Web;
    using Microsoft.AspNet.SignalR;
    using SignalRDemo.App_Start;
    
    namespace SignalRDemo.SignalR
    {
        public class MySignalRConnection : PersistentConnection
        {
            protected override Task OnConnected(IRequest request, string connectionId)
            {
                if (!AppHelper.ConnectionList.Contains(connectionId))
                {
                    AppHelper.ConnectionList.Add(connectionId);
                }
                Connection.Send(AppHelper.ConnectionList, "New In!");
                return Connection.Send(connectionId, "Welcome!");
            }
    
            protected override Task OnReceived(IRequest request, string connectionId, string data)
            {
                return Connection.Broadcast(data);
            }
    
            protected override Task OnDisconnected(IRequest request, string connectionId, bool stopCalled)
            {
                if (AppHelper.ConnectionList.Contains(connectionId))
                {
                    var oldList = new List<string>();
                    oldList.AddRange(AppHelper.ConnectionList);
                    AppHelper.ConnectionList.Remove(connectionId);
                    return Connection.Send(oldList, "out_" + connectionId);
                }
                return null;
            }
        }
    }

     在Startup.cs中添加

    namespace SignalRDemo
    {
        public class Startup
        {
            public void Configuration(IAppBuilder app)
            {
                // 有关如何配置应用程序的详细信息,请访问 http://go.microsoft.com/fwlink/?LinkID=316888
    
                app.MapSignalR<SignalR.MySignalRConnection>("/mc");
            }
        }
    }

     测试页面

    @{
        ViewBag.Title = "SignalR Demo";
        @Scripts.Render("~/bundles/jquery")
        @Scripts.Render("~/bundles/signalR");
    }
    <style type="text/css">
        .row{
            margin:20px;
        }
    
        .msgbox{
            margin:10px 0;
            height:400px;
            overflow-y:auto;
        }
    </style>
    
    <div class="row">
        <input id="ipt_text" type="text" class="" />
        <input id="submit" type="button" value="发送" />
        <div id="msgshow" class="msgbox">
    </div> </div> <script type="text/javascript"> $(function () { var $ipt_text = $('#ipt_text'), $submit = $('#submit'), $msgshow = $('#msgshow'); var conn = $.connection("/mc"); conn.start().done(function (data) { conn.send('大家好,我是新来的,请多多关照'); }).fail(function (msg) { alert(msg); }); function log(msg) { $msgshow.append('<p>【' + new Date().Format("yyyy-MM-dd hh:mm:ss") + '' + msg + '</p>'); } conn.received(function (msg) { log(msg); }); $submit.on('click', function (e) { var txt = $ipt_text.val(); if (!txt || !txt.length) return; conn.send(txt); }); }); </script>

    至此,整个Demo就写完了,下面是测试页面

    需要注意的是,新建MVC项目的时候如果不是选的MVC模板,很多东西需要自己手动添加,比如 Startup.cs , BundleConfig等等。

    还是记录下添加过程吧

    Startup.cs

    BundleConfig类需要引用System.Web.Optimization.dll,这个需要在Nuget中下载

    搜索Optimization,然后安装

    还需注意的是,如果要使用 @Styles.Render 和@Scripts.Render,还需要在View/Web.config中配置System.Web.Optimization.dll域名

    后续要做的事情还很多哦

    连接认证

    权限控制

    消息队列

    消息过滤

    等等

  • 相关阅读:
    elasticsearch head插件安装
    ELK部署配置使用记录
    windows 安装mysql
    vs2017创建dotnetcore web项目,并部署到centos7上
    CentOS 7 安装jdk
    CentOS 7 配置网络
    Surging 记录
    记录一下地址
    net core 依懒注入 中间件
    Elasticsearch 配置文件
  • 原文地址:https://www.cnblogs.com/qiaoge0923/p/10251525.html
Copyright © 2020-2023  润新知