SignalR 实现web浏览器客户端与服务端的推送功能

简介:

SignalR 是一个集成的客户端与服务器库,基于浏览器的客户端和基于 ASP.NET 的服务器组件可以借助它来进行双向多步对话。 换句话说,该对话可不受限制地进行单个无状态请求/响应数据交换;它将继续,直到明确关闭。 对话通过永久连接进行,允许客户端向服务器发送多个消息,并允许服务器做出相应答复,值得注意的是,还允许服务器向客户端发送异步消息。它和AJax类似,都是基于现有的技术。本身是一个复合体。一般情况下,SignalR会使用Javascript的长轮询( long polling),实现客户端和服务端通信。在WebSockets出现以后,SignalR也支持WebSockets通信。当然SignalR也使用了服务端的任务并行处理技术以提高服务器的扩展性。它的目标整个 .NET Framework 平台,它也不限 Hosting 的应用程序,而且还是跨平台的开源项目,支持Mono 2.10+,觉得它变成是 Web API 的另一种实作选择,但是它在服务端处理联机的功能上比 ASP.NET MVC 的 Web API 要强多了,更重要的是,它可以在 Web Form 上使用。

SignalR 内的客户端库 (.NET/JavaScript) 提供了自动管理的能力,开发人员只需要直接使用 SignalR 的 Client Library 即可,同时它的 JavaScript 库可和 jQuery 完美整合,因此能直接与像 jQuery 或 Knockout.js 一起使用。

SignalR内部有两类对象:

· Persistent Connection:持久性连接,用来解决长时间连接的能力,而且还可以由客户端主动向服务器要求数据,而服务器端也不需要实现太多细节,只需要处理 PersistentConnection 内所提供的五个事件:OnConnected, OnReconnected, OnReceived, OnError 和 OnDisconnect 即可。

· Hub:信息交换器,用来解决 realtime 信息交换的功能,服务器端可以利用 URL 来注册一个或多个 Hub,只要连接到这个 Hub,就能与所有的客户端共享发送到服务器上的信息,同时服务器端可以调用客户端的脚本,不过它背后还是不离 HTTP 的标准,所以它看起来神奇,但它并没有那么神奇,只是 JavaScript 更强,强到可以用像 eval() 或是动态解释执行的方式,允许 JavaScript 能够动态的加载与执行方法调用而己。

SignalR 将整个交换信息的行为封装得非常漂亮,客户端和服务器全部都使用 JSON 来沟通,在服务器端声明的所有 hub 的信息,都会一般生成 JavaScript 输出到客户端,.NET 则是依赖 Proxy 来生成代理对象,这点就和 WCF/.NET Remoting 十分类似,而 Proxy 的内部则是将 JSON 转换成对象,以让客户端可以看到对象。

下面我们来针对Persistent Connection和Hub 做个Demo试试:

新建一个ASP.NET MVC项目MvcApplicationSignalR,通过Nuget添加SignalR的包。

新建一个类MyConnection 继承自 PersistentConnection ,引用SignalR命名空间,重写OnReceivedAsync 的方法,并要求 SignalR 对传入的信息做广播

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using SignalR; 
using System.Threading.Tasks;

namespace MvcApplicationSignalR 

   public  class MyConnection : PersistentConnection

    { 
       protected override Task OnReceivedAsync(IRequest request, string connectionId, string data) 
        { 
            // Broadcast data to all clients 
            data = string.Format("数据是:{0} 时间是:{1}", data, DateTime.Now.ToString()); 
            return Connection.Send(connectionId, data); 
        }

    } 
}

接着在 Global.asax 中加入对应路由信息,这会由 SignalR 的路由表来处理 Metadata 的输出工作,红色部分代码:

protected void Application_Start() 

    RouteTable.Routes.MapConnection<MyConnection>("echo", "echo/{*operation}");

 

这样服务器端就完成了。现在我们在项目中Master、View (Home/Index),然后加入必要的代码:

<head> 
    <meta charset="utf-8" /> 
    <title>@ViewBag.Title</title> 
    <link href="@Url.Content("~/Content/Site.css")" rel="stylesheet" type="text/css" /> 
    <script src="@Url.Content("~/Scripts/jquery-1.6.4.min.js")" type="text/javascript"></script> 
    <script src="@Url.Content("~/Scripts/modernizr-1.7.min.js")" type="text/javascript"></script> 
    <script src="@Url.Content("~/Scripts/jquery.signalR-0.5.2.min.js")" type="text/javascript"></script> 
</head>

@{ 
    ViewBag.Title = "Home Page"; 

<script type="text/javascript"> 
    $(function () { 
        var connection = $.connection('echo');

        connection.received(function (data) { 
            $('#messages').append('<li>' + data + '</li>'); 
        });

        connection.start();

        $("#broadcast").click(function () { 
            connection.send($('#msg').val()); 
        }); 
        $("#btnStop").click(function () { 
            connection.stop(); 
        }); 
    });

</script> 
<h2>@ViewBag.Message</h2> 
<input type="text" id="msg" /> 
<input type="button" id="broadcast" value="发送" /> 
<input type="button" id="btnStop" value="停止" /> 
<ul id="messages"> 
</ul>

运行起来就是这个效果:

image

下面我们来展示 SignalR 的另一个功能:由服务器端调用客户端的 JavaScript 脚本的功能,而这个功能的要求必须是要实现成 Hub 的模式,因此我们可以顺便看到如何实现一个 Hub 类型的 SignalR 应用程序。

向项目中加入一个类Chat继承自 Hub 类 (这是 Hub 应用程序的要求) :

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Web; 
using SignalR.Hubs; 
using System.Threading.Tasks; 
using System.Threading;

namespace MvcApplicationSignalR 

   [HubName("geffChat")] 
   public class Chat : Hub  
   { 
       public void SendMessage(string message) 
       { 
           Clients.sendMessage(message); 
       } 
   } 
}

这段程序代码的用意是,在连接进到 Hub 时,将连接代码加到联机用户的集合中,等会就会使用到,因为我们会依照客户端的 ID 来调用客户端脚本。

1. HubName:这个 atttibute 代表 client 端要如何建立对应 server 端对象的 proxy object。通过 HubName , server 端的 class name才不会被 client 绑死。如果没有设定,则会以 server 端 class name 为 HubName 默认值。

2. 继承 Hub:继承 Hub 之后,很多对应的设计就都不用写了,我们只需要把注意力放在 client 如何送 request 给 server的 hub , server 如何通知 client 即可。

3. public void SendMessage(string message) ,就像 WebService Method 或 PageMethod 一般, client 端通过 proxy object ,可以直接调用 server 端这个方法。后续会介绍到如何在页面上使用。

4. Clients 属性:代表所有有使用 Chat 的页面。而 Clients 的型别是 dynamic ,因为要直接对应到 JavaScript 的对象。

5. Clients.sendMessage(message):代表 server 端调用 Clients 上的 sendMessage 方法,也就是 JavaScript 的方法。

6. 总结: Chat 对象职责就是当 client 端调用SendMessage() 方法后,要把这个 message ,送给所有 client 页面上呈现。以达到聊天室的功能。

服务端的做完了,开始制作客户端,同样在Home/Index页面上增加以下html代码

<%--很重要的一个参考,一定要加,且在这一行之前,一定要先参考jQuery.js与signalR.js--%> 
<script src="@Url.Content("~/signalr/hubs")" type="text/javascript"></script>

@{ 
    ViewBag.Title = "Home Page"; 

<script type="text/javascript"> 
    $(function () { 
        var connection = $.connection('/echo');    

        connection.received(function (data) { 
            $('#messages').append('<li>' + data + '</li>'); 
        });

        connection.start();

        $("#broadcast").click(function () { 
            connection.send($('#msg').val()); 
        }); 
        $("#btnStop").click(function () { 
            connection.stop(); 
        });

        // 建立对应server端Hub class的对象,请注意geffChat的第一个字母要改成小写 
        var chat = $.connection.geffChat;

        // 定义client端的javascript function,供server端hub,通过dynamic的方式,调用所有Clients的javascript function 
        chat.sendMessage = function (message) { 
            //当server端调用sendMessage时,将server push的message数据,呈现在wholeMessage中 
            $('#wholeMessages').append('<li>' + message + '</li>'); 
        };

        $("#send").click(function () { 
            //调用叫server端的Hub对象,将#message数据传给server 
            chat.sendMessage($('#message').val()); 
            $('#message').val(""); 
        });

        //把connection打开 
        $.connection.hub.start();

    });

</script> 
<h2>@ViewBag.Message</h2> 
<input type="text" id="msg" /> 
<input type="button" id="broadcast" value="发送" /> 
<input type="button" id="btnStop" value="停止" /> 
<ul id="messages"> 
</ul>

<div> 
    <input type="text" id="message" /> 
    <input type="button" id="send" value="发送" /> 
    <div> 
        聊天室内容: 
        <br /> 
        <ul id="wholeMessages"> 
        </ul> 
    </div> 
</div>

1. 先引用 jQuery 与 signalR 的 js 文件。

2. 很重要的一个步骤:加入一个 js 引用,其路径为「根目录/signalr/hubs」。 SignalR 会建立相关的 JavaScript,放置于此。

3. 通过 $.connection.『server 端的 HubName』,即可建立对应该 hub 的 proxy object。要注意,首字母需小写。

4. 定义 client 端上,供 server 端通知的 JavaScript function,这边的例子是 sendMessage。

5. 当按下发送按钮时,调用 server 端的 SendMessage() 方法,只需要直接通过 proxy object 即可。要注意,首字母需小写。

6. 记得透过 $.connection.hub.start() ,把 connection 打开。

image

注意:SingalR 会自动生成一个siganlr/hub 的桥接js..,在本机使用localhost测试都不会有问题。当部署到IIS的时候会发生404错误,是由于被IIS误判可能是虚拟目录…,解决方法是在web.config加入一段:

<!-- 加入下面这一段-->

<system.webServer>

<validation validateIntegratedModeConfiguration="false" />

<modules runAllManagedModulesForAllRequests="true">

</modules>

</system.webServer>

参考:

实例代码:MvcApplicationSignalR


本文转自左正博客园博客,原文链接:http://www.cnblogs.com/soundcode/p/4191013.html,如需转载请自行联系原作者

相关文章
|
1月前
|
监控 Linux PHP
【02】客户端服务端C语言-go语言-web端PHP语言整合内容发布-优雅草网络设备监控系统-2月12日优雅草简化Centos stream8安装zabbix7教程-本搭建教程非docker搭建教程-优雅草solution
【02】客户端服务端C语言-go语言-web端PHP语言整合内容发布-优雅草网络设备监控系统-2月12日优雅草简化Centos stream8安装zabbix7教程-本搭建教程非docker搭建教程-优雅草solution
81 20
|
2月前
|
Web App开发 编解码 vr&ar
使用Web浏览器访问UE应用的最佳实践
在3D/XR应用开发中,尤其是基于UE(虚幻引擎)开发的高精度场景,传统终端因硬件局限难以流畅运行高帧率、复杂效果的三维应用。实时云渲染技术,将渲染任务转移至云端服务器,降低终端硬件要求,确保用户获得流畅体验。具备弹性扩展、优化传输协议、跨平台支持和安全性等优势,适用于多种终端和场景,特别集成像素流送技术,帮助UE开发者实现低代码上云操作,简化部署流程,保留UE引擎的强大开发能力,确保画面精美且终端轻量化。
129 17
使用Web浏览器访问UE应用的最佳实践
|
1月前
|
监控 关系型数据库 MySQL
【01】客户端服务端C语言-go语言-web端PHP语言整合内容发布-优雅草网络设备监控系统-硬件设备实时监控系统运营版发布-本产品基于企业级开源项目Zabbix深度二开-分步骤实现预计10篇合集-自营版
【01】客户端服务端C语言-go语言-web端PHP语言整合内容发布-优雅草网络设备监控系统-硬件设备实时监控系统运营版发布-本产品基于企业级开源项目Zabbix深度二开-分步骤实现预计10篇合集-自营版
34 0
|
3月前
|
人工智能 API 数据库
Browser Use:开源 AI 浏览器助手,自动完成网页交互任务,支持多标签页管理、视觉识别和内容提取等功能
Browser Use 是一款专为大语言模型设计的智能浏览器工具,支持多标签页管理、视觉识别、内容提取等功能,并能记录和重复执行特定动作,适用于多种应用场景。
1200 0
Browser Use:开源 AI 浏览器助手,自动完成网页交互任务,支持多标签页管理、视觉识别和内容提取等功能
|
4月前
|
人工智能 前端开发 计算机视觉
Inpaint-Web:纯浏览器端实现的开源图像处理工具
在刷短视频时,常看到情侣在景区拍照被路人“抢镜”,男朋友用手机将路人“P”掉,既贴心又有趣。最近我发现了一个纯前端实现的开源项目——inpaint-web,可在浏览器端删除照片中的部分内容,非常酷。该项目基于 WebGPU 和 WASM 技术,支持图像修复与放大,已在 GitHub 上获得 5.1k Star。项目地址:[GitHub](https://github.com/lxfater/inpaint-web)。
115 3
 Inpaint-Web:纯浏览器端实现的开源图像处理工具
|
4月前
|
存储 缓存 前端开发
Web端IM聊天消息该不该用浏览器本地存储?一文即懂!
鉴于目前浏览器技术的进步(主要是HTML5的普及),在Web网页端IM聊天应用的技术选型阶段,很多开发者都会纠结到底该不该像原生移动端IM那样将聊天记录缓存在浏览器的本地,还是像传统Web端即时通讯那样继续存储在服务端?本文将为你简洁明了地讲清楚浏览器本地存储技术(Web Storage),然后你就知道到底该怎么选择了。
74 1
|
5月前
|
Web App开发 XML JavaScript
Python 操作浏览器:让 Python 和 Web 世界合二为一
Python 操作浏览器:让 Python 和 Web 世界合二为一
134 3
|
5月前
|
SQL 安全 关系型数据库
PHP作为一种流行的服务端脚本语言,在Web开发领域具有显著的优势
【10月更文挑战第11天】PHP作为一种流行的服务端脚本语言,在Web开发领域具有显著的优势
85 0
|
7月前
|
API UED 开发者
如何在Uno Platform中轻松实现流畅动画效果——从基础到优化,全方位打造用户友好的动态交互体验!
【8月更文挑战第31天】在开发跨平台应用时,确保用户界面流畅且具吸引力至关重要。Uno Platform 作为多端统一的开发框架,不仅支持跨系统应用开发,还能通过优化实现流畅动画,增强用户体验。本文探讨了Uno Platform中实现流畅动画的多个方面,包括动画基础、性能优化、实践技巧及问题排查,帮助开发者掌握具体优化策略,提升应用质量与用户满意度。通过合理利用故事板、减少布局复杂性、使用硬件加速等技术,结合异步方法与预设缓存技巧,开发者能够创建美观且流畅的动画效果。
126 0
|
4月前
|
JavaScript 前端开发 数据处理
模板字符串和普通字符串在浏览器和 Node.js 中的性能表现是否一致?
综上所述,模板字符串和普通字符串在浏览器和 Node.js 中的性能表现既有相似之处,也有不同之处。在实际应用中,需要根据具体的场景和性能需求来选择使用哪种字符串处理方式,以达到最佳的性能和开发效率。
130 63

热门文章

最新文章