在 Asp.NET MVC 中使用 SignalR 实现推送功能

使用SignalR实现推送功能的Asp.NET MVC应用程序 在Asp.NET MVC应用程序中,SignalR使用Hub来处理服务器端和客户端之间的通信。创建一个新的类文件,命名为"MyHub.cs",并继承自SignalR的Hub类。在该类中,您可以定义服务器端的方法,以供客户端调用。在创建好的Asp.NET MVC项目中,您需要安装SignalR库。完成以上步骤后,您可以运行Asp.NET MVC应用程序,并在浏览器中访问应用程序的URL。在上面的代码中,我们定义了一个名为"SendMessage"的方法,该方法接受一个字符串参数"message"。 阅读详情

一,简介
Signal 是微软支持的一个运行在 Dot NET 平台上的 html websocket 框架。它出现的主要目的是实现服务器主动推送(Push)消息到客户端页面,这样客户端就不必重新发送请求或使用轮询技术来获取消息。

 
二,实现机制
SignalR 的实现机制与 .NET WCF 或 Remoting 是相似的,都是使用远程代理来实现。在具体使用上,有两种不同目的的接口:PersistentConnection 和 Hubs,其中 PersistentConnection 是实现了长时间的 Javascript 轮询(类似于 Comet),Hub 是用来解决实时信息交换问题,它是利用 Javascript 动态载入执行方法实现的。SignalR 将整个连接,信息交换过程封装得非常漂亮,客户端与服务器端全部使用 JSON 来交换数据。

 

下面就 Hubs 接口的使用来讲讲整个流程:

1,在服务器端定义对应的 hub class;

2,在客户端定义 hub class 所对应的 proxy 类;

3,在客户端与服务器端建立连接(connection);

4,然后客户端就可以调用 proxy 对象的方法来调用服务器端的方法,也就是发送 request 给服务器端;

5,服务器端接收到 request 之后,可以针对某个/组客户端或所有客户端(广播)发送消息。

 

三,Hub 示例教程
1,工具准备
SignalR 运行在 .NET 4.5 平台上,所以需要安装 .NET 4.5。为了方便演示,本示例使用 ASP.NET MVC 在 Win 7 系统来实现。这需要安装 ASP.NET MVC 3 或 ASP.NET MVC 4。

 

2,建立工程
打开 VS2010/VS2012 新建名为 SignalRTutorial 的 ASP.NET MVC 3 Web Application 工程,选择 Internet Application 模板, Razor 视图引擎以及勾选 Use HTMl 5 标签。


 
3,安装 SignalR
打开 NuGet 的 package manager console(Tools->Library package manager),输入:install-package SignalR.Sample,回车安装。如图所示:


4,实现 Hub 服务器端代码
向工程中新建 SignalR 目录,在其中添加 ChatHub.cs 文件,内容如下:

namespace SignalTutorial.SignalR
{
    [HubName("chat")]
    public class Chat : Hub
    {
        public void Send(string clientName, string message)
        {
            //var toSelfinfo = "You had sent message " + message;
            //Caller.addSomeMessage(clientName, toSelfinfo);

            // Call the addMessage method on all clients
            Clients.addSomeMessage(clientName, message);
            //Clients[Context.ConnectionId].addSomeMessage(clientName, data);
        }
    }
}
在上面的代码中:

1),HubName 这个特性是为了让客户端知道如何建立与服务器端对应服务的代理对象,如果没有设定该属性,则以服务器端的服务类名字作为 HubName 的缺省值;

2),Chat 继承自 Hub,从下面 Hub 的接口图可以看出:Hub 支持向发起请求者(Caller),所有客户端(Clients),特定组(Group) 推送消息。


3),public void Send(string clientName, string message) 这个接口是被客户端通过代理对象调用的;

4),Clients 是 Hub 的属性,表示所有链接的客户端页面,它和 Caller 一样是 dynamic,因为要直接对应到 Javascript 对象;

5),Clients.addSomeMessage(clientName, message); 表示服务器端调用客户端的 addSomeMessage 方法,这是一个 Javascript 方法,从而给客户端推送消息。

6),总结:这里实现的服务很简单,就是当一个客户端调用 Send 方法向服务器发送 message 后,服务器端负责将该 message 广播给所有的客户端(也可以给特定组或特定客户端,见屏蔽代码),以实现聊天室的功能。

 

5,实现 Hub 客户端代码
1),引用 SignalR Javascript

为了简化引用 SignalR 脚本操作,我直接在 View/Shared/_Layout.cshtml 中引入 SignalR 及其他脚本:

<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.5.1.min.js")" type="text/javascript"></script>
        <script src="@Url.Content("~/Scripts/jquery-1.6.4.js")" type="text/javascript"></script>
        <script src="@Url.Content("~/Scripts/jquery-ui-1.8.24.js")" type="text/javascript"></script>
        <script src="@Url.Content("~/Scripts/jquery.signalR-0.5.3.js")" type="text/javascript"></script>
        <script src="@Url.Content("~/Scripts/modernizr-1.7.min.js")" type="text/javascript"></script>
        <script src="@Url.Content("~/signalr/hubs")" type="text/javascript"></script>
    </head>
注意:signalR 依赖于 jquery,所以 signalR 必须放在 jquery 之后,而 hubs 又必须放在 signalR 之后。

然后在 body 部分加入 HubChat Tab:

<li>@Html.ActionLink("HubChat", "HubChat", "Home")</li>
 

2),生成访问页面

在 HomeController 中添加如下方法:

public ActionResult HubChat()
{
    ViewBag.ClientName = "用户-" + Rnd.Next(10000, 99999);
    return View();
}
这里由服务器根据随机数来设定客户端的名字,不够严谨,因为随机数生成的名字不是唯一的的,在这里仅为简化演示,实际应用中应该使用 GUID 。

然后生成对应的 View:HubChat.cshtml

@model dynamic

@{
    ViewBag.Title = "title";
}

<script src="@Url.Content("~/Scripts/hubDemo.js")" type="text/javascript"></script>
<script type="text/javascript">
    $(document).ready(function () {
    });
</script>

<h2>Hub Chat</h2>

<div>
    <input type="text" id="Placeholder" value="@ViewBag.ClientName" hidden="true"/>
    <input type="text" id="msg" />
    <input type="button" id="broadcast" value="广播" />
   
    <br />
    <br />

    <h3>
        消息记录: (你是:<span id="MyClientName">@ViewBag.ClientName</span>):
    </h3>

    <ul id="messages">
    </ul>
</div>
在上面的页面代码中,我添加了名为 hubDemo.js 的脚本,这将在下面介绍;此外还有一个id 为 Placeholder 的隐藏 input 控件,这是为了向 Javascript 中传递客户端的名字。

 

3),编写 Javascript

向 Scripts 目录添加新的 Javescript 脚本:hubDemo.js。其内容如下:

$(function () {

    var myClientName = $('#Placeholder').val();

    // Proxy created on the fly
    var chat = $.connection.chat;

    // Declare a function on the chat hub so the server can invoke it
    chat.addSomeMessage = function (clientName, message) {
        writeEvent('<b>' + clientName + '</b> 对大家说: ' + message, 'event-message');
    };

    $("#broadcast").click(function () {
        // Call the chat method on the server
        chat.send(myClientName, $('#msg').val())
                            .done(function () {
                                console.log('Sent message success!');
                            })
                            .fail(function (e) {
                                console.warn(e);
                            });
    });

    // Start the connection
    $.connection.hub.start();

    //A function to write events to the page
    function writeEvent(eventLog, logClass) {
        var now = new Date();
        var nowStr = now.getHours() + ':' + now.getMinutes() + ':' + now.getSeconds();
        $('#messages').prepend('<li class="' + logClass + '"><b>' + nowStr + '</b> ' + eventLog + '.</li>');
    }
});
上面代码有详细的注释,下面再讲讲关键之处:

1,首先获取客户端页面的名字;

2,然后通过 $.connection.chat 建立对应服务器端 Hub 类的代理对象 chat;

3,定义客户端的 Javascript 方法 addSomeMessage ,服务器通过 dynamic 方式调用客户端的该方法以实现推送功能。在这里每当收到服务器推送来的消息,就在客户端页面的 messages 列表表头插入该消息。

4,当点击广播按钮时,客户端通过代理对象调用服务器端的 send 方法以实现向服务器发送消息。

5,通过 $.connection.hub.start(); 语句打开链接。

 

6),编译运行 Hub 示例
在多个浏览器窗口打开页面,效果如下:



 

四,Persistent Connection 示例教程
1,实现服务器端代码
1),编写服务器 PersistentConnection 代码
向工程中 SignalR 目录中添加 PersistentConnection.cs 文件,内容如下:

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

namespace SignalTutorial.SignalR
{
    public class MyConnection : PersistentConnection
    {
        protected override Task OnConnectedAsync(IRequest request, string connectionId)
        {
            return Connection.Broadcast("Connection " + connectionId + " connected");
        }

        protected override Task OnReconnectedAsync(IRequest request, IEnumerable<string> groups, string clientId)
        {
            return Connection.Broadcast("Client " + clientId + " re-connected");
        }

        protected override Task OnReceivedAsync(IRequest request, string connectionId, string data)
        {
            var info = data + ". ConnectionId is [" + connectionId + "]";
            // return Connection.Send(connectionId, info);  

            // Broadcast data to all clients
            return Connection.Broadcast(info);  
        }

        protected override Task OnDisconnectAsync(string connectionId)
        {
            return Connection.Broadcast("Connection " + connectionId + " disconncted");
        }

        protected override Task OnErrorAsync(Exception error)
        {
            return Connection.Broadcast("Error ocurred " + error);
        }
    }
}
在上面的代码中:

1,MyConnection 继承自 PersistentConnection,这样我们就能在客户端连接,重连接,断开连接,发送消息以及连接出错的情况下进行相关的处理。从下面的 PersistentConnection 接口中可以看到,PersistentConnection 同样支持组进行推送。

 


2,推送消息由 PersistentConnection 的属性 Connection 来提供,它继承自 IConnection 接口,该接口提供两个函数来实现对特定客户端的推送和广播功能。

System.Threading.Tasks.Task Send(string signal, object value)
System.Threading.Tasks.Task Broadcast(object value)

 

2),配置访问路由
为了支持客户端访问,需要在路由表中进行配置。打开 Global.asax.cs ,修改 Application_Start() 函数如下:

protected void Application_Start()
{
    AreaRegistration.RegisterAllAreas();

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

    RegisterGlobalFilters(GlobalFilters.Filters);
    RegisterRoutes(RouteTable.Routes);

    // Make connections wait 50s maximum for any response. After
    // 50s are up, trigger a timeout command and make the client reconnect.
    GlobalHost.Configuration.ConnectionTimeout = TimeSpan.FromSeconds(50);
    //DisconnectTimeout
    //HeartBeatInterval
    //KeepAlive
}
 

在上面的代码中,我将 echo 及其子路径的访问映射到 MyConnection 上,并设置连接超时时间为 50 s。在这里还可以设置其他的一些参数,如断连超时时间,心跳间隔等。

 

2,实现客户端代码
1),生成访问页面

在前面三 Hub 示例教程的基础上,我们向该工程加入使用 Persistent Connection 的演示。和前面一样,向 _Layout.cshtml 中加入 PersistentChat Tab:

<li>@Html.ActionLink("PersistentChat", "PersistentChat", "Home")</li>
然后在 HomeController 中添加如下方法:

public ActionResult PersistentChat()
{
    ViewBag.ClientName = "用户-" + Rnd.Next(10000, 99999);
    return View();
}
这里由服务器根据随机数来设定客户端的名字,不够严谨,因为随机数生成的名字不是唯一的的,在这里仅为简化演示,实际应用中应该使用 GUID 。

然后生成对应的 页面: PersistentChat.cshtml:

@model dynamic

@{
    ViewBag.Title = "title";
}

<script src="@Url.Content("~/Scripts/persistent.js")" type="text/javascript"></script>

<h2>Persistent Chat</h2>

<div>
    <input type="text" id="Placeholder" value="@ViewBag.ClientName" hidden="true"/>
    <input type="text" id="msg" />
    <input type="button" id="broadcast" value="广播" />

    <br />
    <br />
   
    <h3>
        消息记录: (你是:<span id="MyClientName">@ViewBag.ClientName</span>):
    </h3>

    <ul id="messages">
    </ul>

</div>
在上面的页面代码中,我添加了名为 persistent.js 的脚本,这将在下面介绍;此外还有一个id 为 Placeholder 的隐藏 input 控件,这是为了向 Javascript 中传递客户端的名字。

 

2),编写 Javascript

向 Scripts 目录添加新的 Javescript 脚本:persistent.js。其内容如下:

$(function () {

    var myClientName = $('#Placeholder').val();

    var connection = $.connection('/echo');

    connection.received(function (data) {
        var msg = new String(data);
        var index = msg.indexOf("#");
        var clientName = msg.substring(0, index);
        var content = msg.substring(index + 1);

        if (clientName == null || clientName == "") {
            writeEvent('<b>' + "系统消息" + '</b>: ' + content, 'event-message');
        }
        else {
            writeEvent('<b>' + clientName + '</b> 对大家说: ' + content, 'event-message');
        }
    });

    connection.start();

    $("#broadcast").click(function () {
        var msg = myClientName + "#" + $('#msg').val();
        connection.send(msg);
    });

    //A function to write events to the page
    function writeEvent(eventLog, logClass) {
        var now = new Date();
        var nowStr = now.getHours() + ':' + now.getMinutes() + ':' + now.getSeconds();
        $('#messages').prepend('<li class="' + logClass + '"><b>' + nowStr + '</b> ' + eventLog + '.</li>');
    }
});
上面的代码基本与前面的 Hub 实现相同,在此就不再一一讲述。有两点值得说明:

1,创建连接时,指定路径为 "/echo",该路径在服务器端的路由映射表被映射为 MyConnection,因而这个连接就被指向前面提供的 MyConnection。

2,将 clientName 信息放入 message 中,并用 # 将 clientName 和消息内容连接成一个 msg。

3,编译运行 Persistent 示例

 

winform与MVC开发的SignalR相互发送信息 winform与MVC开发的SignalR相互发送信息 今天刚更新。跟昨天的只能winform发送 立即下载

相关推荐

高精度SAR ADC设计实战:从建模到版图的16位1MSPS实现

本文详细介绍了16位1MSPS高精度SAR ADC的设计过程,从建模到版图实现的完整流程。重点探讨了分段电容阵列设计、校准算法实现及版图匹配等关键技术,展示了如何在180nm工艺下实现92.5dB SNDR和109.6dB SFDR的高性能指标。文章特别强调了整数桥接电容设计对提升匹配精度的关键作用,为高精度模数转换器设计提供了实用参考。

weixin_33724046的博客 436

Asp.NET MVC 中使用 SignalR 实现推送功能

一,简介 Signal 是微软支持的一个运行在 Dot NET 平台上的 html websocket 框架。它出现的主要目的是实现服务器主动推送(Push)消息到客户端页面,这样客户端就不必重新发送请求或使用轮询技术来获取消息。 可访问其官方网站:https://github.com/SignalR/获取更多资讯。 二、Asp.net SignalR 是个什...

weixin_34419321的博客 750

Isaac Sim 使用经验(配置要求,云服务器)

Google Colab及AutoDL都是在docker内运行,其中google colab并不支持docker指令,而依照AutoDL的相关文档,AutoDL并不直接提供docker指令。2. Google Colab/AutoDL 不支持图形化界面,图形渲染等任务,所以没有办法使用Omniverse Streaming进行直播,从而更好的对结果进行展示。对于第一点,或许存在直接手动复现镜像的可能,但是考虑到Isaac Sim/Isaac Lab由于比较新,可能不够稳定,因此还是按照官方文档进行部署。

weixin_44211433的博客 4587

winform服务器消息推送,winform项目——仿QQ即时通讯程序12:服务端程序补充及优化...

原标题:winform项目——仿QQ即时通讯程序12:服务端程序补充及优化上一篇文章大概完成了服务端程序,今天继续做项目的时候发现还有一些功能没有做,还有几处地方不够完善。不做好就会影响客户端程序的编写,因此,本篇文章将对服务端程序进行补充和优化。 首先是未完成的功能:离线消息的检测与发送用户连接到服务器之后,不仅要开启线程接收、转发消息,也要检测数据库中是否有离线消息,如果有就发送给用户并将离线...

weixin_32921457的博客 702

【Zemax光学设计实训一】---单透镜光学设计

建立一个焦距为100mm、入瞳直径为25mm的单透镜系统,该透镜中心厚度为4mm,其两个面的曲率半径分别为100mm、-100mm,全视场2w=10°。该系统在可见光下工作,采用BK7玻璃,光阑设置在人射光线遇到的透镜的第一个光学表面;并对其展开优化。

yh的博客 3616

电源管理芯片PMIC

(Power Management Integrated Circuits,简称:将电源电压转换为电子设备各部分所需的适当电压水平,包括升压(Boost)、降压(Buck)和升降压(Buck-Boost)转换。:控制和限制流向电子设备各部分的电流,以保护组件免受过电流损害。:管理多个电源轨,为不同的部分提供稳定的电能控制。电源轨指电路板上传输电力的线路。电源监控:提供过电压、欠电压、过电流、过热和短路保护,以防止电子设备损坏。:通过高效的电源转换技术,减少能量损耗,提高能源利用效率。

qq_42786033的博客 1万+

在 Asp.NET MVC 中使用 SignalR 实现推送功能 [转]

在 Asp.NET MVC 中使用 SignalR 实现推送功能 罗朝辉 (http://blog.csdn.net/kesalin) CC许可,转载请注明出处 一,简介 Signal 是微软支持的一个运行在 Dot NET 平台上的 html websocket 框架。它出现的主要目的是实现服务器主动推送(Push)消息到客户端页面,这样客户端就不必重新发送请求或使用轮...

diaguo7961的博客 99

拥有AI助手便能解放双手?——抖音直播脚本的生成

科技改变生活,AI助手帮你完成抖音创作!

Scientist_的博客 2351
上一篇: WebSocket简单使用
下一篇: jquery_api_1.9 中文手册
江南野鹤
博客等级 码龄23年 54粉丝 41原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值