ASP.NET SignalR入门

前言
  之前在培训ASP.NET WebAPI的时候有提过SignalR这个技术,但当时只是讲了是用来做什么的,并没有多说。因为自己也是画图找资料的时候见到的。后来当一直关注的前端大神贤心发布LayIM2.0之后,于是对Web聊天产生了兴趣。那么在.NET平台下的Web聊天有哪些呢?查找资料发现了ASP.NET SignalR。于是乎...So...Just do it!

简介
  按照惯例,先介绍一下什么是SignalR。简单的说,ASP .NET SignalR 是一个ASP .NET 下的类库,可以在ASP .NET 的Web项目中实现实时通信。
  什么是实时通信的Web呢?就是让客户端(Web页面)和服务器端可以互相通知消息及调用方法,当然这是实时操作的。
  WebSockets是HTML5提供的新的API,可以在Web网页与服务器端间建立Socket连接,当WebSockets可用时(即浏览器支持Html5)SignalR使用WebSockets,当不支持时SignalR将使用其它技术来保证达到相同效果。
  SignalR当然也提供了非常简单易用的高阶API,使服务器端可以单个或批量调用客户端上的JavaScript函数,并且非常 方便地进行连接管理,例如客户端连接到服务器端,或断开连接,客户端分组,以及客户端授权,使用SignalR都非常 容易实现。

作用
  SignalR 将与客户端进行实时通信带给了ASP .NET 。当然这样既好用,而且也有足够的扩展性。以前用户需要刷新页面或使用Ajax轮询才能实现的实时显示数据,现在只要使用SignalR,就可以简单实现了。
  最重要的是您无需重新建立项目,使用现有ASP .NET项目即可无缝使用SignalR。

Owin规范
  OWIN是Open Web Server Interface for .NET的首字母缩写,他的定义如下:
  OWIN在.NET Web Servers与Web Application之间定义了一套标准接口,OWIN的目标是用于解耦Web Server和Web Application。基于此标准,鼓励开发者开发简单、灵活的模块,从而推进.NET Web Development开源生态系统的发展。
  正如你看到的这样,OWIN是接口、契约,而非具体的代码实现,仅仅是规范(specifications),所以要实现自定义基于OWIN的Web Server必须要实现此规范。
  历时两年(2010-2012),OWIN的规范终于完成并且当前版本是1.0,在OWIN的官网上可以看到更具体的信息。
  实际上,OWIN的规范非常简单,他定义了一系列的层(Layer),并且他们的顺序是以堆(Stack)的形式定义,如下所示。OWIN中的接口被称之为应用程序委托或者AppFunc,用来在这些层之间通信。

  

  OWIN定义了4层:
  Host:主要负责应用程序的配置和启动进程,包括初始化OWIN Pipeline、运行Server。
  Server:绑定套接字并监听的HTTP请求然后将Request和Response的Body、Header封装成符合OWIN规范的字典并发送到OWIN Middleware Pipeline中
  Middleware:称之为中间件、组件,位于Server与Application之间,用来处理发送到Pipeline中的请求
  Application:这是具体的应用程序代码,只不过我们将他们注册到OWIN Pipeline中去处理HTTP 请求,成为OWIN管道的一部分
  Application Delegate
  OWIN规范另一个重要的组成部分是接口的定义,用于Server和Middleware的交互。他并不是严格意义上的接口,而是一个委托并且每个OWIN中间件组件必须提供。
  详见:http://www.cnblogs.com/OceanEyes/p/thinking-in-asp-net-mvc-what-is-owin.html
Katana
  微软引入并推广OWIN,同时依照OWIN规范,实现了Katana。Host.SystemWeb, Host.HttpListener 都是Katana的一个组件。
  Katana的基本原则
  ● 可移植性:从HostàServeràMiddleware,每个Pipeline中的组件都是可替换的,并且第三方公司和开源项目的Framework都是可以在OWIN Server上运行,也就是说不受平台限制,从而实现跨平台。
  ● 模块化:每一个组件都必须保持足够独立性,通常只做一件事,以混合模块的形式来满足实际的开发需求
  ● 轻量和高效:因为每一个组件都是模块化开发,而且可以轻松的在Pipeline中插拔组件,实现高效开发
  Katana 体系结构
  Katana实现了OWIN的Layers,所以Katana的体系结构和OWIN一致,如下所示:

  

  1.)Host :宿主Host被OWIN规范定义在第一层(最底层),他的职责是管理底层的进程(启动、关闭)、初始化OWIN Pipeline、选择Server运行等。
  Katana为我们提供了3中选择:
  ● IIS / ASP.NET :使用IIS是最简单和向后兼容方式,在这种场景中OWIN Pipeline通过标准的HttpModule和HttpHandler启动。使用此Host你必须使用System.Web作为OWIN Server
  ● Custom Host :如果你想要使用其他Server来替换掉System.Web,并且可以有更多的控制权,那么你可以选择创建一个自定义宿主,如使用Windows Service、控制台应用程序、Winform来承载Server。
  ● OwinHost :如果你对上面两种Host还不满意,那么最后一个选择是使用Katana提供的OwinHost.exe:他是一个命令行应用程序,运行在项目的根部,启动HttpListener Server并找到基于约束的Startup启动项。OwinHost提供了命令行选项来自定义他的行为,比如:手动指定Startup启动项或者使用其他Server(如果你不需要默认的HttpListener Server)。
  2.)Server
  Host之后的Layer被称为Server,他负责打开套接字并监听Http请求,一旦请求到达,根据Http请求来构建符合OWIN规范的Environment Dictionary(环境字典)并将它发送到Pipeline中交由Middleware处理。Katana对OWIN Server的实现分为如下几类:
  ● System.Web:如前所述那样,System.Web和IIS/ASP.NET Host两者彼此耦合,当你选择使用System.Web作为Server ,Katana System.Web Server把自己注册为HttpModule和HttpHandler并且处理发送给IIS的请求,最后将HttpRequest、HttpResponse对象映射为OWIN环境字典并将它发送至Pipeline中处理。
  ● HttpListener:这是OwinHost.exe和自定义Host默认的Server。
  ● WebListener:这是ASP.NET vNext默认的轻量级Server,他目前无法使用在Katana中
  3)Middleware
  Middleware(中间件)位于Host、Server之后,用来处理Pipeline中的请求,Middleware可以理解为实现了OWIN应用程序委托AppFun的组件。
  Middleware处理请求之后并可以交由下一个Pipeline中的Middleware组件处理,即链式处理请求,通过环境字典可以获取到所有的Http请求数据和自定义数据。Middleware可以是简单的Log组件,亦可以为复杂的大型Web Framework,诸如:ASP.NET Web API、Nancy、SignlR等,如下图所示:Pipeline中的Middleware用来处理请求:

  

  4.)Application
  最后一层即为Application,是具体的代码实现,比如ASP.NET Web API、SignalR具体代码的实现。

  详见:http://www.cnblogs.com/OceanEyes/p/thinking-in-asp-net-mvc-what-is-katana.html

说了那么多,接下来开始上代码。

  开始之前,准备工作:必须安装.NET Framework 4.5 , Visual Studio 2013+,VS2012需要安装其他软件和配置,也可能会出现一些位置问题(我用的VS2015)

持久连接:
1、新建一个空项目


2、新建一个OWIN Startup类,名称随意,这里以Startup为例。

3、新建SignalR永久连接类,名称随意,这里以MyConnection为例。

当该类添加完成后,会自动添加SignalR的相关引用和Script(如图所示)

4、打开Startup.cs添加对MyConnection的映射

5、新建一个HTML页面,名称随意。在新建的HTML页面上引用jquery-1.10.2.js和jquery.signalR-2.1.2.min.js

6、与服务端通讯,写入下图红框内的代码

打开浏览器,F12打开控制台,如图显示,说明连接成功。

为什么会是输出Welcome呢?

  $.connection("/myconn");创建了一个连接,连接是哪儿呢,“/myconn”就是之前在Startup类中定义的MyConnection中映射路径。当建立连接后,调用OnConnected方法,如下:

  

现在来进行消息发送    

 1      var conn = $.connection("/myconn");//创建连接
 2         //开始连接
 3         conn.start(function () {
 4             console.log("已连接");
 5         }).done(function() {
 6             conn.send("你好!");
 7         });
 8         //接受消息
 9         conn.received(function (data) {
10             console.log(data);
11         });

SignalR.js提供了发送接口send()  <注意:start()方法是异步方法,send()只能在回调函数中执行,或者自定义参数标识。>

那么服务端是怎么接收的呢?

还是在MyConnection中,此处将你发送的信息给广播出去

下边用持久连接类来演示一个简单的聊天室的功能,只是简单实现功能,只做演示,勿喷。

直接上代码:

 1 using System;
 2 using System.Collections.Generic;
 3 using System.Linq;
 4 using System.Threading.Tasks;
 5 using System.Web;
 6 using Microsoft.AspNet.SignalR;
 7 using Newtonsoft.Json;
 8
 9 namespace SignalRDemo
10 {
11     public class MyConnection : PersistentConnection
12     {
13
14         /// <summary>
15         /// 建立新连接时调用
16         /// </summary>
17         /// <param name="request">当前连接的请求</param>
18         /// <param name="connectionId">进行重新连接的客户端的 ID。</param>
19         /// <returns>连接操作完成时将完成的 System.Threading.Tasks.Task。 </returns>
20         protected override Task OnConnected(IRequest request, string connectionId)
21         {
22             return Connection.Send(connectionId, "Welcome!");
23         }
24
25         /// <summary>
26         /// 从连接接收数据时调用
27         /// </summary>
28         /// <param name="request">当前连接的请求</param>
29         /// <param name="connectionId"> 发送数据的连接的 ID。</param>
30         /// <param name="data">发送到连接的负载。</param>
31         /// <returns>接收操作完成时将完成的 System.Threading.Tasks.Task。</returns>
32         protected override Task OnReceived(IRequest request, string connectionId, string data)
33         {
34             var mode = JsonConvert.DeserializeObject<MyChart>(data);
35             if (mode.Action == "welcome")
36             {
37                 this.Groups.Add(connectionId, mode.RoomName);
38
39                 //除了当前这个人,该房间的其他人都会受到welcom new user的消息。
40                 return this.Groups.Send(mode.RoomName, string.Format("欢迎新用户进入房间: {0}", mode.RoomName), connectionId);
41             }
42             else
43             {
44                 //发送的消息,排除当前这个人
45                 return this.Groups.Send(mode.RoomName, string.Format("用户{0}说:{1}", connectionId, mode.Data), connectionId);
46             }
47         }
48     }
49
50
51     public class MyChart
52     {
53         public string RoomName { get; set; }
54         public string Data { get; set; }
55         public string Action { get; set; }
56
57     }
58 }

MyConnection.cs

 1 <!DOCTYPE html>
 2 <html>
 3 <head>
 4     <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
 5     <title></title>
 6     <meta charset="utf-8" />
 7     <script src="Scripts/jquery-1.10.2.js"></script>
 8     <script src="Scripts/jquery.signalR-2.1.2.min.js"></script>
 9
10 </head>
11 <body>
12     <h1>SignalR</h1>
13     <input type="button" value="房间一" id="room1" />
14     <input type="text" id="msg" />
15     <input type="button" value="发送" id="send" />
16     <script type="text/javascript">
17         $(function () {
18             var conn = $.connection("/myconn");
19             //conn.logging = true;
20             var isconn = false;
21             conn.start(function () {
22                 isconn = true;
23             });
24
25             $("#room1").click(function () {
26                 if (isconn) {
27                     conn.send({ RoomName: "room1", Action: "welcome" });
28                 }
29             });
30             $("#send").click(function () {
31                 if (isconn) {
32                     conn.send({
33                         RoomName: "room1",
34                         Action: "2",
35                         Data: $("#msg").val()
36                     });
37                 }
38
39             });
40             conn.connectionSlow(function (data) {
41
42             });
43             conn.disconnected(function (data) {
44
45             });
46             conn.error(function (data) { });
47             conn.received(function (data) {
48                 console.log(data);
49             });
50         });
51
52     </script>
53 </body>
54 </html>

HtmlPage.html

效果如下:

Demo

以上我们都是在“持久连接”层上面做的操作,类似socket这样的模式。。。我们真正有用的操作是由一个OnReceived方法。

这样看起来,是不是很单一?而且也非常不人性化,那么为了解决这种问题,singlaR给我们封装了更高一层的应用。

那么这个就叫做Hub,这个Hub使用的是类似于RPC的调用模式。

关于Hub,将会在下一篇文章中来讲细细讲解。

官方教程https://www.asp.net/signalr/overview/getting-started/tutorial-getting-started-with-signalr

时间: 2024-10-02 03:45:18

ASP.NET SignalR入门的相关文章

Asp.net SignalR 实现服务端消息推送到Web端

原文:http://www.cnblogs.com/wintersun/p/4148223.html 之前的文章介绍过Asp.net SignalR,  ASP .NET SignalR是一个ASP .NET 下的类库,可以在ASP .NET 的Web项目中实现实时通信.  今天我们来实现服务端消息推送到Web端,   首先回顾一下它抽象层次图是这样的: 实际上 Asp.net SignalR 2 实现 服务端消息推送到Web端, 更加简单. 为了获取更好的可伸缩性, 我们引入消息队列, 看如下

ASP.NET SignalR 与 LayIM2.0 配合轻松实现Web聊天室(一) 之 基层数据搭建,让数据活起来(数据获取)

大家好,本篇是接上一篇 ASP.NET SignalR 与 LayIM2.0 配合轻松实现Web聊天室(零) 前言  ASP.NET SignalR WebIM系列第二篇.本篇会带领大家将 LayIM界面中的数据动态化.当然还不涉及即时消息通讯,如果你已经搞定了数据界面,那么本文您可以简单的看一下,或者略过. 进入正题,layim帮我们定义好了数据规则,我们只要写一个接口实现那个json规范就可以了,剩下的事情就交给layim去做,看一下json格式.(对应文件夹:demo/json/getLi

ASP.NET MVC4入门到精通系列目录汇总(转)

序言 最近公司在招.NET程序员,我发现好多来公司面试的.NET程序员居然都没有 ASP.NET MVC项目经验,其中包括一些工作4.5年了,甚至8年10年的,许多人给我的感觉是:工作了4.5年,Web开发依旧停留在拖控件的水平,最最基本的算 法,递归.排序(我不要求快速排序,你会冒泡就行了)都不会,数据库方面,很基础的SQL都写不出,分组过滤也不会,更别提性能了,问下数据优化经验,除 了回答加索引基本就没下文了.当然,一些过去N年都是做ASP.NET WebForm开发的,不熟悉MVC,那也没

22、ASP.NET MVC入门到精通——搭建项目框架

本系列目录:ASP.NET MVC4入门到精通系列目录汇总 前面的章节,说了ASP.NET MVC项目中常用的一些技术和知识点,更多的是理论上面的东西,接下来,我将通过一个简单的OA项目来应用我们之前涉及到的一些技术,为了兼顾初学者,所以我尽量把操作步骤说得足够详细.(本来想用VS2015来演示MVC5开发的,无奈家里的笔记本是11年2月份的老爷机了,一直未曾舍得换,因为配置的缘故,笔记本不堪负重,难以安装最新版本的开发工具,只装了VS2012,当然,还有一个原因就是现在公司也是使用VS2012

26、ASP.NET MVC入门到精通——后台管理区域及分离、Js压缩、css、jquery扩展

本系列目录:ASP.NET MVC4入门到精通系列目录汇总 有好一段时间没更新博文了,最近在忙两件事:1.看书,学习中...2.为公司年会节目做准备,由于许久没有练习双截棍了,难免生疏,所以现在临时抱佛脚.深圳最近的天气反常,许多人感冒了,我也成为其中之一,大家注意身体... 这一篇,我来简单的讲一下接下来项目中会用到的一些杂七杂八的技术. 区域及分离 在15.ASP.NET MVC入门到精通——MVC-路由中,我已经简要说明了区域的分离. 1.右键单击Web项目,“添加”——“区域”,区域名,

ASP.NET MVC入门到精通——14.MVC请求管道

本系列目录:ASP.NET MVC4入门到精通系列目录汇总 ASP.NET MVC的请求管道和ASP.NET请求管道基本上一模一样,如果你对ASP.NET请求管道十分熟悉的话,你只要关注一下不同点.看懂下面两张图,你就基本上明了了,不明天的地方,用reflector工具查看MVC的源码,没其它的..NET框架的源码里面几乎涉猎了各种设计模式.这一节的内容,我也不知道怎么说,都在图里面了,看图比直接用文字说明要明了得多,比较这些东西还是比较抽象的,如果你时间充裕,建议看下MVC的源码.怎么看?就找

第一章ASP.NET SignalR简介

1.1概述: ASP.NET SignalR是微软新开发的类库,为的是帮助ASP.NET开发人员很方便地开发实时网络功能. SignalR允许服务器端和客户端之间进行双向通信.服务器端现在可以连接到客户端并且把内容瞬间推送出去,而不是一个客户端不断请求服务器端从而才能获取新数据(不是通过轮询去拉服务器端数据,而是服务器端主动推送数据到客户端).SignalR支持Web Sockets套接字,并且当使用旧版浏览器的时候会自动使用相关兼容的技术.SignalR包括它的API接口,用于连接管理的解耦(

Asp.net MVC入门视频教程

编程开发 > Asp.net视频教程 > Asp.net MVC入门视频教程 > 1.传统web处理方式和mvc处理方式 上传日期:2014-08-16 10:02:45  相关摘要:  - 怎么一创建传统补间就成了上下移动的了 - web 服务器 第一次进入站点速度慢是什么问题?? - EF中怎么处理像Sql多表连接的问题? 2.mvc项目会自动导入mvc程序集 上传日期:2014-08-16 10:14:51  相关摘要:  - Asp.net mvc 可以不用js吗 - 项目发布的

Asp.Net MVC5入门学习系列④

原文:Asp.Net MVC5入门学习系列④ 添加Model且简单的使用EF 对于EF(EntityFramework)不了解的朋友可以去百度文科或者在园子里搜一些简资源看下,假如和我一样知道EF的概念,那么就知道EF有一个code first的特性,什么意思呢!说的通俗简单明了点就是:通过代码映射到数据库!有朋友会说这里不是添加Model说这个EF干啥呢!说这个code first呢就是我们在一会添加Model的同时我打算利用EF的code first特性把我们的Model映射到数据库,这样我