• 一步一步学习SignalR进行实时通信_2_Persistent Connections


    一步一步学习SignalR进行实时通信_2_Persistent Connections

    标签(空格分隔): SignalR


    前言

    上一篇文章简单的介绍了下SignalR,从此篇文章就开始对SignalR进行剖析。在介绍Persistent connections之前,先简单介绍下安装signalR的方法。

    我的开发环境:win10+vs2013

    安装

    1. 首先我们新建一个空的MVC5的项目
      空MVC项目
    2. 通过Nuget[^Nuget]安装SignalR,通过Tools->Nuget Package Manager->Package Manager Console打开Package Manager Console
    3. 输入安装语句Install-Package Microsoft.AspNet.SignalR
      安装完成

      可以看到添加了JQuery和SignalR2.0

    Persistent Connections

    Persistent Connections的字面意思是持久连接,它有点类似于Sockets,在服务端和客户端都可以发送或接收数据。

    映射并配置持久连接

    如果我们要是实现基于PersistentConnection的实时信息传输,首先第一步我们需要在服务器启动时对_SignalR_进行配置。由于我们是基于_Owin_来实现_SignalR_的所以,我们在Startup中找到Configuration中配置,类似如果我们要实现其他的Owin框架我们也可以在这里进行配置。

    1. 映射

      using System;
      using System.Threading.Tasks;
      using Microsoft.Owin;
      using Owin;
      using SignalR_2.Models;
      //设置Owin的启动项
      [assembly: OwinStartup(typeof(SignalR_1.Startup))]
      namespace SignalR_·
      {
          public class Startup
          {
              public void Configuration(IAppBuilder app)
              {
                  // For more information on how to configure your application, visit http://go.microsoft.com/fwlink/?LinkID=316888
                  app.MapSignalR<EchoConnection>("/echo");
              }
          }
      }
      

      通过MapSignalR()方法来做映射,/echo表示将会映射到/echo,后面我我们转到MapSignalR定义
      MapSignalR

      MapSignalR()是一个扩展方法,它有许多重载方法,而我们主要关心的就是如图所示的泛型方法。这个方法的TConnection要求是一个PersistentConnection类型。

      好了,到此为止我们已经知道我们需要什么了,没必要继续深究下去。通过以上的研究,很明显,我们需要构造这么一个类去继承PersistentConnection来实现_SignalR_服务

    2. 实现SignalR服务
      我们新建一个类叫做EchoConnection,代码如下:

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

      namespace SignalR_1.Models
      {
      public class EchoConnection : PersistentConnection
      {
      /// <summary>
      /// 当前连接数
      /// </summary>
      private static int _connections = 0;
      /// <summary>
      /// 连接建立时执行
      /// </summary>
      /// <param name="request"></param>
      /// <param name="connectionId"></param>
      /// <returns></returns>
      protected override async Task OnConnected(IRequest request, string connectionId)
      {
      //原子操作,防止多条现成同时+1而只做一次变化
      Interlocked.Increment(ref _connections);
      await Connection.Send(connectionId, "Hi, " + connectionId + "!");
      await Connection.Broadcast("新连接 " + connectionId + "开启. 当前连接数: " + _connections);
      }
      /// <summary>
      /// 连接关闭时执行
      /// </summary>
      /// <param name="request"></param>
      /// <param name="connectionId"></param>
      /// <returns></returns>
      protected override Task OnDisconnected(IRequest request, string connectionId)
      {
      //原子操作,防止多条现成同时-1而只做一次变化
      Interlocked.Decrement(ref _connections);
      return Connection.Broadcast(connectionId + " 连接关闭. 当前连接数: " + _connections);
      }
      /// <summary>
      /// 连接开始时执行
      /// </summary>
      /// <param name="request"></param>
      /// <param name="connectionId"></param>
      /// <param name="data"></param>
      /// <returns></returns>
      protected override Task OnReceived(IRequest request, string connectionId, string data)
      {
      var message = connectionId + ">> " + data;
      return Connection.Broadcast(message);
      }
      }
      }

      我们定义了一个EchoConnection类继承PersistentConnetion,并写了OnConnectedOnDisconnectedOnReceived、三个方法,大致功能是当客户端连接时,服务器会通过Send()方法向它打招呼,参数是他的ConnectionId,并发送广播消息给所有客户端,并使总连接数+1,当客户端关闭连接时,服务器会广播给所有客户端XXX连接关闭,并使总连接数-1

    3. 客户端实现
    <!DOCTYPE html>
    <html xmlns="http://www.w3.org/1999/xhtml">
    <head>
        <title>persistent connections</title>
        <script src="Scripts/jquery-1.10.2.min.js"></script>
        <script src="Scripts/jquery.signalR-2.0.0.min.js"></script>
    </head>
    <body>
        <h1>Echo service</h1>
        <div>
            <input type="text" id="text" />
            <button id="send">Send</button>
        </div>
        <script>
            $(function () {
                var connection = $.connection("/echo");
                connection.logging = true;
    
            connection.received(<span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">data</span>) </span>{
                $(<span class="hljs-string">"body"</span>).append(data + <span class="hljs-string">"&lt;br /&gt;"</span>);
            });
    
            connection.error(<span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">err</span>) </span>{
                alert(<span class="hljs-string">"存在一个错误. 
    "</span> +
                            <span class="hljs-string">"Error: "</span> + err.message);
            });
    
            connection.start().done(<span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params"></span>) </span>{
                $(<span class="hljs-string">"#send"</span>).click(<span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params"></span>) </span>{
                    connection.send($(<span class="hljs-string">"#text"</span>).val());
                    $(<span class="hljs-string">"#text"</span>).val(<span class="hljs-string">""</span>).focus();
                });
            });
        });
    </span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>
    

    </body>
    </html>

    对上面的代码有疑问看下面的图片
    客户端和服务器

    如图所示:左边是客户端的javascript代码,右边是服务器的代码
    当客户端调用start方法时,会执行服务器的OnConnected方法
    当客户端点击发送按钮发送消息时,服务端会在OnReceived中接收到消息
    当服务端对消息进行发送或广播给客户端时,客户端receive会接收到此消息

    结束语

    这里通过PersistentConnection实现了在线聊天的简单例子。

    注意在项目运行期间,我出现过几次程序集版本不对的情况,若出现此种情况,通过Install-Package XXX 重装该程序集或Update-Package XXX升级该程序集,一般均可解决

    源码下载
    本文发布至作业部落

    参考文献

    SignalR Programming in Microsoft ASP.NET pdf 下载
    [^Nuget]: NuGet 是免费、开源的包管理开发工具。

    每天收获一点点
    标签: SignalR
    5
    0
    « 上一篇:一步一步学习SignalR进行实时通信_1_简单介绍
    » 下一篇:一步一步学习SignalR进行实时通信_3_通过CORS解决跨域
    	</div>
  • 相关阅读:
    MyBatis之三:多表联合查询
    MyBatis之二:简单增删改查
    MyBatis之一:入门
    如何用Maven创建web项目(具体步骤)
    Maven3.2创建webapp项目过程中问题以及解决方案
    纯前端下载数据Excel文档
    centos7 yum无法正常工作
    Element ui table selection 分页支持保存已经选中的数据,同时支持随时删除选中的数据,并设置默认选择
    删除排序数组中的重复选项
    列表数据(包含父节点关系)转化为树形结构
  • 原文地址:https://www.cnblogs.com/owenzh/p/11163066.html
Copyright © 2020-2023  润新知