越是到年底越是感觉浑身无力,看着啥也不想动,只期盼着年终奖的到来以此来给自己打一针强心剂。估摸着大多数人都跟我一样犯着这样浑身无力的病,感觉今年算是没挣到啥钱,但是话也不能这么说,搞得好像去年挣到钱了似的。不过该做的事情还是得到,因为毕竟自己拿着工资,拿一天钱就得干一天活,无论自己觉得工资给的多还是少,觉得少可以辞职不干,拿着工资就证明自己愿意接受,既然愿意接受,那就没有理由不努力去干活,我觉得这是作为一个员工最起码的信念。

隔着有一段时间没写博客了,反正最近各种乱七八糟的事都在发生,不过不管怎么样,事情总会慢慢过去。(最近没事,正在研究神学,待有所感悟再与大家分享。)

这一篇博客主要介绍一下ASP.NET SignalR持久连接层的相关内容,如有写的不到位和错误的地方,还望大家多多指正。

一.ASP.NET SignalR概述:

谈到ASP.NET SignalR大多数人应该会比较的熟悉,因在我们的mvc项目中,使用到ASP.NET SignalR的地方还是比较多的。

ASP.NET SignalR是ASP.NET开发人员的库,它简化了向应用程序添加实时Web功能的过程。实时网络功能能够让服务器代码在连接的客户端可用时立即将内容推送到连接的客户端,而不是让服务器等待客户端请求新数据。SignalR可用于向ASP.NET应用程序添加任何类型的“实时”Web功能。任何时候用户刷新网页,看看新的数据或页面实现长轮询来获取新的数据,它是使用SignalR的候选人。示例包括仪表板和监视应用程序,协作应用程序(如同时编辑文档),作业进度更新和实时表单。

SignalR还支持需要来自服务器的高频更新的全新类型的web应用。SignalR自动处理连接管理,并允许您同时向所有连接的客户端广播消息。SignalR支持“服务器推送”功能,其中服务器代码可以使用远程过程调用(RPC)在浏览器中调用客户端代码。SignalR的应用可以扩展到使用服务总线。

SignalR提供了一个用于创建从服务器端.NET代码调用客户端浏览器(和其他客户端平台)中的JavaScript函数的服务器到客户端远程过程调用(RPC)的简单API。SignalR还包括用于连接管理(例如,连接和断开事件)的API和分组连接。SignalR提供了一个用于创建从服务器端.NET代码调用客户端浏览器(和其他客户端平台)中的JavaScript函数的服务器到客户端远程过程调用(RPC)的简单API。SignalR还包括用于连接管理(例如,连接和断开事件)的API和分组连接。

(以上描述摘自MSDN)

上面介绍了ASP.NET SignalR的一些基本概念和操作,接下来看一下ASP.NET SignalR的抽象层,由底层向上以此为:Internet协议,传输(WebSockets,Server-SentEvents,foreverFrame,长轮询),持久连接层,Hub层。

由以上的结构图可知ASP.NET SignalR的抽象层结构,在服务器端,当连接打开或关闭、接收数据、给客户端发送信息时,将接受到通知;在客户端,打开或关闭连接,发送或接收任何数据。在ASP.NET SignalR的持久连接层中,有一个核心对象:PersisterConnection类,接下来我们具体了解一下这个类的一些方法。

二.ASP.NET SignalR持久连接层服务端核心对象方法解析:

ASP.NET SignalR中的每一个持久层都可以通过某一个URL从外部进行访问。为保持客户端和服务器之间持久连接的开放性,并使用传输在这样的连接上发送数据,这个用来访问SignalR持久连接的底层API提供了隐藏固有复杂性的抽象层。

1.PersisterConnection类的事件方法:

在PersisterConnection中包含几个事件方法,这几个方法都是虚方法,如下:

    OnConnected():在建立新连接时调用。

    OnReconnected():在超时后连接重新连接时调用。

    OnReceived():从连接接收数据时调用。

    OnDisconnected():当连接正常断开或由于超时时调用。

以上的4个方法中,返回的类型都是TaskAsyncHelper.Empty,如下源码:

    /// <summary>
/// 从连接接收数据时调用。
/// </summary>
/// <param name="request">当前连接的IRequest。</param>
<param name="connectionId">发送数据的连接的ID。</param>
<param name="data">有效负载发送到连接。</param>
/// <returns>
///System.Threading.Tasks.Task在接收操作完成时完成。/// </returns>
protected virtual Task OnReceived(IRequest request, string connectionId, string data)
{
return TaskAsyncHelper.Empty;
}

以上的方法都是异步方法,用以实现代码的异步执行,或者返回一个能够通过某个Task对象表示和异步执行的后台任务,在方法的传入参数中,代码中已经做类对应的介绍。如果需要进一步了解TaskAsyncHelper.Empty的相关信息,可以具体查看System.Threading.Tasks.Task命名空间中的类。

2.ProcessRequest():处理所有的请求。

PersisterConnection类的ProcessRequest()方法是用与OWIN入口点,该方法存在多个重载版本,现在只介绍一个重载的源码:

    public virtual Task ProcessRequest(HostContext context)
{
if (context == null)
throw new ArgumentNullException("context");
if (!this._initialized)
throw new InvalidOperationException(string.Format((IFormatProvider) CultureInfo.CurrentCulture, Resources.Error_ConnectionNotInitialized, new object[]));
if (PersistentConnection.IsNegotiationRequest(context.Request))
return this.ProcessNegotiationRequest(context);
if (PersistentConnection.IsPingRequest(context.Request))
return PersistentConnection.ProcessPingRequest(context);
this.Transport = this.GetTransport(context);
if (this.Transport == null)
return PersistentConnection.FailResponse(context.Response, string.Format((IFormatProvider) CultureInfo.CurrentCulture, Resources.Error_ProtocolErrorUnknownTransport, new object[]), );
string connectionToken = context.Request.QueryString["connectionToken"];
if (string.IsNullOrEmpty(connectionToken))
return PersistentConnection.FailResponse(context.Response, string.Format((IFormatProvider) CultureInfo.CurrentCulture, Resources.Error_ProtocolErrorMissingConnectionToken, new object[]), );
string connectionId;
string message;
int statusCode;
if (!this.TryGetConnectionId(context, connectionToken, out connectionId, out message, out statusCode))
return PersistentConnection.FailResponse(context.Response, message, statusCode);
this.Transport.ConnectionId = connectionId;
Task<string> groupsToken = this.Transport.GetGroupsToken();
Func<string, PersistentConnection, HostContext, Task> func = (Func<string, PersistentConnection, HostContext, Task>) ((g, pc, c) => pc.ProcessRequestPostGroupRead(c, g));
HostContext hostContext = context;
Func<string, PersistentConnection, HostContext, Task> successor;
return TaskAsyncHelper.FastUnwrap(TaskAsyncHelper.Then<string, PersistentConnection, HostContext, Task>(groupsToken, successor, this, hostContext));
}

由以上的源码可以看出,该方法为一个异步虚方法,并且接受一个参数HostContext表示当前请求。当一个PersistentConnection的管道完成时,返回一个System.Threading.Tasks.Task。Transport.GetGroupsToken()用与获取组令牌。ProcessRequest()的另一个重载版本是OWIN的入口。

3.TryGetConnectionId():用与获取ConnectionId。

看到ConnectionId应该都不会陌生,因为在前面介绍的4中事件方法中有一个参数就是ConnectionId,该参数是一个唯一标识符,他和初始化通信过程中通过SiganlR自动产生的连接有关。默认情况下,SignalR框架将使用一个guid进行标识。

可以使用该连接符给某些特定的客户端直接发送消息,或是对他们实施任何类型的个性化监视。

接下来,我们具体看一下源码:

internal bool TryGetConnectionId(HostContext context, string connectionToken, out string connectionId, out string message, out int statusCode)
{
string str1 = (string) null;
connectionId = (string) null;
message = (string) null;
statusCode = ;
try
{
str1 = this.ProtectedData.Unprotect(connectionToken, "SignalR.ConnectionToken");
}
catch (Exception ex)
{
TraceSource trace = this.Trace;
string format = "Failed to process connectionToken {0}: {1}";
object[] objArray = new object[];
int index1 = ;
string str2 = connectionToken;
objArray[index1] = (object) str2;
int index2 = ;
Exception exception = ex;
objArray[index2] = (object) exception;
trace.TraceInformation(format, objArray);
}
if (string.IsNullOrEmpty(str1))
{
message = string.Format((IFormatProvider) CultureInfo.CurrentCulture, Resources.Error_ConnectionIdIncorrectFormat, new object[]);
return false;
}
string[] strArray = str1.Split(PersistentConnection.SplitChars, );
connectionId = strArray[];
if (string.Equals(strArray.Length > ? strArray[] : string.Empty, PersistentConnection.GetUserIdentity(context), StringComparison.OrdinalIgnoreCase))
return true;
message = string.Format((IFormatProvider) CultureInfo.CurrentCulture, Resources.Error_UnrecognizedUserIdentity, new object[]);
statusCode = ;
return false;
}

该方法返回bool值,接受5个参数,分别为:HostContext请求内容,connectionToken连接令牌,connectionId连接ID,message消息,statusCode状态代码。进入方法后,首先判断参数信息是否符合要求。ProtectedData.Unprotect()方法用与取消保护,接受传入的连接令牌。PersistentConnection.GetUserIdentity()用与获取用户身份。

4.VerifyGroups():用与验证组。

在我们的实际项目中,一般是针对某一个用户进行消息的处理,如果想要将消息按照组别进行操作应该怎么处理,在SignalR提供了一个VerifyGroups方法。

 internal IList<string> VerifyGroups(string connectionId, string groupsToken)
{
if (string.IsNullOrEmpty(groupsToken))
return ListHelper<string>.Empty;
string str1 = (string) null;
try
{
str1 = this.ProtectedData.Unprotect(groupsToken, "SignalR.Groups.v1.1");
}
catch (Exception ex)
{
TraceSource trace = this.Trace;
string format = "Failed to process groupsToken {0}: {1}";
object[] objArray = new object[];
int index1 = ;
string str2 = groupsToken;
objArray[index1] = (object) str2;
int index2 = ;
Exception exception = ex;
objArray[index2] = (object) exception;
trace.TraceInformation(format, objArray);
}
if (string.IsNullOrEmpty(str1))
return ListHelper<string>.Empty;
string[] strArray = str1.Split(PersistentConnection.SplitChars, );
string a = strArray[];
string json = strArray.Length > ? strArray[] : string.Empty;
string b = connectionId;
int num = ;
if (!string.Equals(a, b, (StringComparison) num))
return ListHelper<string>.Empty;
return (IList<string>) JsonSerializerExtensions.Parse<string[]>(this.JsonSerializer, json);
}

该方法返回一个List<string>集合,接受两个参数connectionId,groupsToken进行分组操作。ProtectedData.Unprotect()方法用与取消保护,接受传入的连接令牌。在SignalR中一般在处理消息请求时,需要进行取消保护这一步操作。Split()对取消保护操作后返回的数据进行分割获取一个数组。

三.总结:

以上是简单的介绍SignalR的持久层的一些方法,并没有提供一些基本样例,因为个人觉得在网上还是有自己多的demo,微软的官网也提供的更为详尽的操作说明,所以在这里就不做这一方面的重复介绍。

ASP.NET SignalR2持久连接层解析的更多相关文章

  1. Asp.Net SignalR - 持久连接类

    持久连接类 通过SignalR持久连接类可以快速的构建一个即时通讯的应用,上篇博文已经我们创建一个owin Startup类和一个持久连接类来完成我们的工作,然后在Startup类的Configura ...

  2. asp.net signalR 专题—— 第二篇 对PersistentConnection持久连接的快速讲解

    上一篇我们快速的搭建了一个小案例,但是并没有对其中的方法进行介绍,这一篇我来逐一解析下. 一:从override的那些方法说起 不管怎么样,我们先上代码,如下: public class MyConn ...

  3. WebSocket 是什么原理?为什么可以实现持久连接?

    https://www.zhihu.com/question/20215561   作者:Ovear链接:https://www.zhihu.com/question/20215561/answer/ ...

  4. WebSocket是什么原理?为什么可以实现持久连接?

    作者:Ovear 链接:https://www.zhihu.com/question/20215561/answer/40316953来源:知乎著作权归作者所有.商业转载请联系作者获得授权,非商业转载 ...

  5. WebSocket 是什么原理?为什么可以实现持久连接?(转载)

    本文转载自知乎,来源如下: 作者:Ovear链接:https://www.zhihu.com/question/20215561/answer/40316953来源:知乎著作权归作者所有.商业转载请联 ...

  6. 【转】WebSocket 是什么原理?为什么可以实现持久连接?

    WebSocket是HTML5出的东西 也就是说HTTP协议没有变化 但HTTP是不支持持久连接的(长连接,循环连接的不算)或者说WebSocket干脆就不是基于HTTP来执行的.但是...说不通啊. ...

  7. 一文带你看懂WebSocket 的原理?为什么可以实现持久连接?

    工作之余在知乎上偶然看到一篇回帖,瞬间觉得之前看的那么多资料都不及这一篇让我对 websocket 的认知深刻易懂,之前看总完总觉得一知半解云里雾里.所以与大家共同分享一下一起学习.比较喜欢这种博客理 ...

  8. LVSDR模型与持久连接

    LVS之DR模型以及持久连接 LVS的简单介绍 linux virtual server 简单来讲lvs是一段内核代码 类似于netfilter本身是一框架但不提供任何功能,但是在这框架上提供了能够根 ...

  9. WebSocket是什么原理,为什么可以实现持久连接

    本文摘抄自知乎,原文标题:WebSocket 是什么原理?为什么可以实现持久连接? Websocket只是协议而已. 一.WebSocket是HTML5出的东西(协议),也就是说HTTP协议没有变化, ...

随机推荐

  1. BZOJ 3997 TJOI2015 组合数学

    分析一下样例就可以知道,求的实际上是从左下角到右上角的最长路 因为对于任意不在这个最长路的上的点,都可以通过经过最长路上的点的路径将这个点的价值减光 (可以用反证法证明) 之后就是一个非常NOIP的D ...

  2. SQL Server Mobile 和 .NET 数据访问接口之间的数据类型映射

      .NET 数据类型 SQL Server Mobile 数据类型 binary varbinary boolean bit byte tinyint byte[] varbinary dateti ...

  3. 编程之美:1.9高效率安排见面会 图的m着色问题 回溯法

    原书问题,可以转换为图的m着色问题 ,下面该问题的代码 这里有参考ppt与code,免积分载 http://download.csdn.net/detail/u011467621/6341195 // ...

  4. WCF的行为与异常-------配置文件说明

    ServiceBehavior and OperationBehavior(这些都是应用在实现类上) http://msdn.microsoft.com/zh-cn/library/system.se ...

  5. 【运维手记】virtualbox中centOS安装增强功能

    在virtualbox安装了centOS,想安装增强功能时,系统提示: building the main Guest Additions module Failed 于是尝试了以下两步操作: (1) ...

  6. 关于haproxy hdr_reg(host) 的一些解释

    I've recently taken over an environment using HAProxy, and I'm attempting to learn the config and wh ...

  7. init进程解析rc文件的相关函数分析

    init进程的源码文件位于system/core/init,其中解析rc文件语法的代码放在五个函数中, init_parse_config_file (init_parser.c), read_fil ...

  8. 【HDOJ】1979 Fill the blanks

    预处理+搜索剪枝.4*4的边界上的数字必须是奇数. /* 1979 */ #include <iostream> #include <sstream> #include < ...

  9. Java数据库增删改查

    数据库为MySQL数据库,Oracle数据库类似: create database db_test;--创建数据库 ';--创建用户 grant all privileges on db_test.* ...

  10. 大四实习准备6_android服务

    2015-5-9 1.服务是什么 android四大组件之一,有一些特点: 1)服务的运行不依赖于用户界面,即使程序被切换到后台.或者用户打开了另外一个应用程序,服务仍然能够保持正常运行.(当对应的程 ...