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方法,如下:
现在来进行消息发送
var conn = $.connection("/myconn");//创建连接
//开始连接
conn.start(function () {
4 console.log("已连接");
5 }).done(function() {
6 conn.send("你好!");
7 });
//接受消息
conn.received(function (data) {
console.log(data);
});
SignalR.js提供了发送接口send() <注意:start()方法是异步方法,send()只能在回调函数中执行,或者自定义参数标识。>
那么服务端是怎么接收的呢?
还是在MyConnection中,此处将你发送的信息给广播出去
下边用持久连接类来演示一个简单的聊天室的功能,只是简单实现功能,只做演示,勿喷。
直接上代码:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System.Web;
using Microsoft.AspNet.SignalR;
using Newtonsoft.Json; namespace SignalRDemo
{
public class MyConnection : PersistentConnection
{ /// <summary>
/// 建立新连接时调用
/// </summary>
/// <param name="request">当前连接的请求</param>
/// <param name="connectionId">进行重新连接的客户端的 ID。</param>
/// <returns>连接操作完成时将完成的 System.Threading.Tasks.Task。 </returns>
protected override Task OnConnected(IRequest request, string connectionId)
{
return Connection.Send(connectionId, "Welcome!");
} /// <summary>
/// 从连接接收数据时调用
/// </summary>
/// <param name="request">当前连接的请求</param>
/// <param name="connectionId"> 发送数据的连接的 ID。</param>
/// <param name="data">发送到连接的负载。</param>
/// <returns>接收操作完成时将完成的 System.Threading.Tasks.Task。</returns>
protected override Task OnReceived(IRequest request, string connectionId, string data)
{
var mode = JsonConvert.DeserializeObject<MyChart>(data);
if (mode.Action == "welcome")
{
this.Groups.Add(connectionId, mode.RoomName); //除了当前这个人,该房间的其他人都会受到welcom new user的消息。
return this.Groups.Send(mode.RoomName, string.Format("欢迎新用户进入房间: {0}", mode.RoomName), connectionId);
}
else
{
//发送的消息,排除当前这个人
return this.Groups.Send(mode.RoomName, string.Format("用户{0}说:{1}", connectionId, mode.Data), connectionId);
}
}
} public class MyChart
{
public string RoomName { get; set; }
public string Data { get; set; }
public string Action { get; set; } }
}
MyConnection.cs
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title></title>
<meta charset="utf-8" />
<script src="Scripts/jquery-1.10.2.js"></script>
<script src="Scripts/jquery.signalR-2.1.2.min.js"></script> </head>
<body>
<h1>SignalR</h1>
<input type="button" value="房间一" id="room1" />
<input type="text" id="msg" />
<input type="button" value="发送" id="send" />
<script type="text/javascript">
$(function () {
var conn = $.connection("/myconn");
//conn.logging = true;
var isconn = false;
conn.start(function () {
isconn = true;
}); $("#room1").click(function () {
if (isconn) {
conn.send({ RoomName: "room1", Action: "welcome" });
}
});
$("#send").click(function () {
if (isconn) {
conn.send({
RoomName: "room1",
Action: "2",
Data: $("#msg").val()
});
} });
conn.connectionSlow(function (data) { });
conn.disconnected(function (data) { });
conn.error(function (data) { });
conn.received(function (data) {
console.log(data);
});
}); </script>
</body>
</html>
HtmlPage.html
效果如下:
以上我们都是在“持久连接”层上面做的操作,类似socket这样的模式。。。我们真正有用的操作是由一个OnReceived方法。
这样看起来,是不是很单一?而且也非常不人性化,那么为了解决这种问题,singlaR给我们封装了更高一层的应用。
那么这个就叫做Hub,这个Hub使用的是类似于RPC的调用模式。
关于Hub,将会在下一篇文章中来讲细细讲解。
官方教程https://www.asp.net/signalr/overview/getting-started/tutorial-getting-started-with-signalr
ASP.NET SignalR入门的更多相关文章
- [Asp.net 开发系列之SignalR篇]专题一:Asp.net SignalR快速入门
一.前言 之前半年时间感觉自己有点浮躁,导致停顿了半年多的时间没有更新博客,今天重新开始记录博文,希望自己可以找回初心,继续沉淀.由于最近做的项目中用到SignalR技术,所以打算总结下Asp.net ...
- ASP.NET SignalR 2.0入门指南
ASP.NET SignalR 2.0入门指南 介绍SignalR ASP.NET SignalR 是一个为 ASP.NET 开发人员的库,简化了将实时 web 功能添加到应用程序的过程.实时Web功 ...
- Asp.Net SignalR 使用记录 技术回炉重造-总纲 动态类型dynamic转换为特定类型T的方案 通过对象方法获取委托_C#反射获取委托_ .net core入门-跨域访问配置
Asp.Net SignalR 使用记录 工作上遇到一个推送消息的功能的实现.本着面向百度编程的思想.网上百度了一大堆.主要的实现方式是原生的WebSocket,和SignalR,再次写一个关于A ...
- Asp.net SignalR 初试和应用笔记一 认识和使用 SignalR
如果你在用QQ,微信.你会知道,广告和消息无处不在.也有好的一面,比如通过QQ或微信,微博等及时聊天功能,你找到了你的初恋,你找到了小学的班级等等. 这里的及时通信在很多应用场所能用到,比如: 1.球 ...
- [置顶]
MVC中使用signalR入门教程
一.前言:每次写总要说一点最近的感想 进入工作快半年了,昨天是最郁闷的一天,我怀疑我是不是得了"星期一综合征",每个星期一很没有状态.全身都有点酸痛,这个可能一个星期只有周末才打一 ...
- Asp.net SignalR 让实时通讯变得简单
巡更项目中,需要发送实时消息,以及需要任务开始提醒,于是便有机会接触到SignalR,在使用过程中,发现用SignalR实现通信非常简单,下面我思明将从三个方面分享一下: 一.SignalR是什么 A ...
- 使用ASP.NET SignalR实现一个简单的聊天室
前言 距离我写上一篇博客已经又过了一年半载了,时间过得很快,一眨眼,就把人变得沧桑了许多.青春是短暂的,知识是无限的.要用短暂的青春,去学无穷无尽的知识,及时当勉励,岁月不待人.今天写个随笔小结记录一 ...
- ASP.NET SignalR介绍
是什么? 简单来说,ASP.NET SignalR是一个开源的实时通讯(real-time)库,有了ASP.NET SignalR,我们可以在 详细介绍参考:https://docs.microsof ...
- 连表查询都用Left Join吧 以Windows服务方式运行.NET Core程序 HTTP和HTTPS的区别 ASP.NET SignalR介绍 asp.net—WebApi跨域 asp.net—自定义轻量级ORM C#之23中设计模式
连表查询都用Left Join吧 最近看同事的代码,SQL连表查询的时候很多时候用的是Inner Join,而我觉得对我们的业务而言,99.9%都应该使用Left Join(还有0.1%我不知道在 ...
随机推荐
- hadoop配置
配置参考博客:(目前有问题,百度说官网的是32bit,现在正在尝试64位 http://www.powerxing.com/install-hadoop-cluster/
- OBS MAC 系统开发(基于mac OS X 10.12)
按照github 上的说明,安装配套软件,和跟踪需要的库 推荐使用homebrew 来安装各种依赖库. 安装Qt后,要配置系统变量 ,这个困扰本人很久:) 成功编译 cmake .. &&am ...
- input placeholder属性 样式修改(颜色,大小,位置)
placeholder属性 样式修改 <!DOCTYPE html> <html> <head> <meta charset="utf-8" ...
- C#设备处理类操作
C#对于处理window操作系统下的设备有天然的优势,对于大多数设备读写等操作来说基本上够了,这里只讨论通过普通的大多数的设备的操作.涉及到两大类SerialPort类,Socket的一些操作.不一定 ...
- CentOS 7 防火墙 firewall 的使用
1.firewalld的基本使用 启动: systemctl start firewalld 查看状态: systemctl status firewalld 停止: systemctl disabl ...
- BZOJ4698: Sdoi2008 Sandy的卡片
差分,枚举一个串的所有后缀,暴力在所有其他串中kmp,复杂度$O(nm^2)$. #include<cstdio> const int N=1005; const int M=105; i ...
- redis 操作 hash 的测试
1>hset setname field value hset stuSet name zhangsan:1 2>hget setname field hget stuset ...
- Openstack学习目录
1.2016.12.27 ceph简介 crush算法 OSD(boject storage device) Mds(cephfs) 使用cephfs时需要安装metadata s ...
- 防火墙iptables
iptables命令可用于配置Linux的包过滤规则,常用于实现防火墙.NAT.咋一看iptables的配置很复杂,掌握规律后,其实用iptables完成指定任务并不难,下面我们通过具体实例,学习ip ...
- Jquery 插件\Js 插件收集
1.linq.js 使得js 的数组像c#的linq操作一下样 http://linqjs.codeplex.com/ 2.分页插件 https://github.com/mricle/Mricode ...