ASP.NET SignalR 是ASP.NET开发库,简化了向应用程序添加实时Web功能的过程。实时Web功能是指服务器代码在连接的客户端可用时立即将内容推送到连接的客户端,而不是让服务器等待客户端请求新数据。

SignalR简介

  • ASP.NET SignalR用于向ASP.NET应用程序添加任何类型的“实时”Web功能。
  • 每当用户刷新网页以查看新数据,或者页面实现长轮询以检索新数据时,它都是使用SignalR的候选者。示例:仪表板和监视应用程序,协作应用程序,作业进度更新和实时表单。
  • SignalR提供一个简单的API,用于创建从服务端.NET代码调用客户端浏览器(或其他客户端平台)中的JavaScript函数的服务端到客户端的远程过程调用(RPC)。
  • SignalR也提供了用于连接管理的API及分组连接。
  • SignalR自动处理连接管理,并允许同时向所有的客户端广播消息,也支持向特定客户端发送消息。客户端和服务端之间的连接是持久的,不向传统的HTTP连接,每次通信重新建立。
  • SignalR支持“服务推送”功能,即服务器代码使用远程过程调用(RPC)调用浏览器中的客户端代码,而不是请求-响应模型。
  • SignalR应用程序可以使用Service Bus,SQL Server或者Redis扩展到数千个客户端。

SignalRCommunication.jpg

SignalR and WebSocket

SignalR在可用的情况下使用新的WebSocket传输,并在必要时回退到旧的传输。

虽然可以直接使用WebSocket编写应用程序,但SignalR已经为你完成了许多额外的功能。

SignalR不必担心WebSocket更新,SignalR将更新以支持底层传输的更改。

Transports and fallbacks

SignalR是对客户端和服务器之间进行实时工作所需的一些传输的抽象,连接开始以HTTP启动,然后在可用时提升为WebSocket。

WebSocket传输有严格要求:服务器使用Windows Server2012或者Window 8以及.NET Framework 4.5。如果不满足这些要求,SignalR将尝试使用其他传输来建立连接。

  • HTML5 transports

    • WebSocket
    • Server Sent Events
  • Comet transports

    • Forever Frame

      仅适用于Internet Explorer,创建一个隐藏的IFrame,向服务器上端点发出请求,然后,服务器不断的向客户端发送脚本,该脚本立即执行,提供了从服务器到客户端的单向实时连接。

    • Ajax long polling

      长轮询,不会创建持久连接,而是使用一个保持打开的请求轮询服务器,直到服务器响应,此时关闭连接,并立即请求新连接。

Connections and Hubs

SignalR API包含两种模式用于在客户端和服务端的通信:

  • 持久连接(Persistent Connections)
  • 集线器(Hubs)

大部分应用程序都使用Hubs API。

Hubs工作原理:

当服务端代码在客户端上调用方法时,将通过活动传输发送数据包,该数据包包含要调用的方法的名称和参数(当对象作为方法参数发送时,使用JSON进行序列化)。然后,客户端将方法名称与客户端代码中定义的方法进行匹配,如果匹配,则将参数反序列化,执行客户端方法。

SignalRArchitecture.jpg

SignalR 1.X

SignalR简化了构建实时应用程序的过程。它包括一个ASP.NET服务器库和一个JavaScript刻客户端库。

聊天演示:

  • 新建ASP.NET Empty Web Application

  • Install-Package Microsoft.AspNet.SignalR -Version 1.1.3

  • 项目自动生成Scripts文件夹,里面包含jQuery和SignalR脚本

    SignalR1.jpg

  • 新建SignalR Hub类,继承Microsoft.AspNet.SignalR抽象类

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    namespace SignalR1
    {
    public class ChatHub : Hub
    {
    public void Send(string name, string message)
    {
    //将消息发送给客户端
    Clients.All.Hello(name, message);
    }
    }
    }
  • 添加全局应用程序类Global.asax文件,注册默认Hub 路由

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    namespace SignalR1
    {
    public class Global : System.Web.HttpApplication
    {

    protected void Application_Start(object sender, EventArgs e)
    {
    //注册默认hubs route:~/signalr/hubs
    RouteTable.Routes.MapHubs();
    }

    protected void Session_Start(object sender, EventArgs e)
    {

    }

    protected void Application_BeginRequest(object sender, EventArgs e)
    {

    }

    protected void Application_AuthenticateRequest(object sender, EventArgs e)
    {

    }

    protected void Application_Error(object sender, EventArgs e)
    {

    }

    protected void Session_End(object sender, EventArgs e)
    {

    }

    protected void Application_End(object sender, EventArgs e)
    {

    }
    }
    }
  • 添加客户端页面ChatPage.html,

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    <!DOCTYPE html>
    <html xmlns="http://www.w3.org/1999/xhtml">
    <head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <title>SignalR Simple Chat</title>
    <style>
    .container {
    background-color: #99ccff;
    border: thick solid #808080;
    padding: 20px;
    margin: 20px;
    }
    </style>
    </head>
    <body>
    <div class="container">
    <input type="text" id="message" />
    <input type="button" id="sendmessage" value="Send" />
    <input type="hidden" id="displayname" />
    <ul id="discussion"></ul>
    </div>

    <!--jQuery脚本引入-->
    <script src="Scripts/jquery-1.6.4.min.js"></script>
    <!--SignalR脚本引入-->
    <script src="Scripts/jquery.signalR-1.1.4.min.js"></script>
    <!--自动生成的SignalR Hub脚本引入-->
    <script src="/signalr/hubs"></script>

    <!--发送消息-->
    <script>
    $(function () {
    //声明一个hub代理,默认引用hub类的驼峰名
    var chat = $.connection.chatHub;
    //创建hub广播消息的方法,回调方法,hub类调用此方法将内容推送到每个客户端
    chat.client.Hello = function (name, message) {
    var encodeName = $('<div />').text(name).html();
    var encodeMsg = $('<div />').text(message).html();

    $("#discussion").append('<li><strong>' + encodeName + '</strong>:&nbsp;&nbsp;' + encodeMsg + '</li>');
    }
    $("#displayname").val(prompt("Enter you name:", ""));
    $("#message").focus();
    //启动连接
    $.connection.hub.start().done(function () {
    $('#sendmessage').click(function () {
    //调用hub上的Send方法
    chat.server.send($('#displayname').val(), $('#message').val());
    $("#message").val('').focus();
    });
    });
    });

    </script>
    </body>
    </html>
  • 调用过程

    • hub类声明公共方法,以便客户端调用它们
    • 使用Microsoft.AspNet.SignalR.Hub.Clients动态属性可以访问所有连接到hub类的客户端
    • 在客户端上调用jQuery函数来更新客户端

    SignalRSendmessage.jpg

    SignalR 2

聊天演示:

  • 将SignalR库添加到ASP.NET Web应用程序
  • 创建Hub类将内容推送到客户端
  • 创建OWIN启动类以配置应用程序
  • 网页中使用SignalR jQuery库从Hub类发送消息和显示更新
  1. 创建ASP.NET Empty Web应用程序

  2. 添加SignalR2 Hub Class(V2),自动生成SignalR Hub类和脚本

    SignalR2.jpg

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    namespace SignalRChat
    {
    public class ChatHub : Hub
    {
    public void Hello(string name, string message)
    {
    Clients.All.hello(name, message);
    }
    }
    }
  3. 添加OWIN Startup Class

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    namespace SignalRChat
    {
    public class Startup
    {
    public void Configuration(IAppBuilder app)
    {
    // 有关如何配置应用程序的详细信息,请访问 http://go.microsoft.com/fwlink/?LinkID=316888
    app.MapSignalR();
    }
    }
    }
  4. 添加页面ChatPage.html

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    <!DOCTYPE html>
    <html xmlns="http://www.w3.org/1999/xhtml">
    <head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <title>SignalR Simple Chat</title>
    <style type="text/css">
    .container {
    background-color: #99CCFF;
    border: thick solid #808080;
    padding: 20px;
    margin: 20px;
    }
    </style>
    </head>
    <body>
    <div class="container">
    <input type="text" id="message" />
    <input type="button" id="sendmessage" value="Send" />
    <input type="hidden" id="displayname" />
    <ul id="discussion"></ul>
    </div>
    <!--Script references-->
    <!--Reference the jQuery library-->
    <script src="Scripts/jquery-1.6.4.min.js"></script>
    <!--Reference the SignalR library-->
    <script src="Scripts/jquery.signalR-2.3.0.min.js"></script>
    <!--Reference the autogenerated SignalR hub script-->
    <script src="signalr/hubs"></script>
    <!--add script to update the page and send message-->
    <script>
    //Declare a proxy to reference the hub
    var chat = $.connection.chatHub;
    //Create a function that the hub can call to broadcast message
    chat.client.hello = function (name, message) {
    // Html encode display name and message.
    var encodedName = $('<div />').text(name).html();
    var encodedMsg = $('<div />').text(message).html();
    // Add the message to the page.
    $('#discussion').append('<li><strong>' + encodedName
    + '</strong>:&nbsp;&nbsp;' + encodedMsg + '</li>');
    }
    //Get the username and store it to prepend to message
    $('#displayname').val(prompt('Enter your name:', ''));
    // Set initial focus to message input box.
    $('#message').focus();
    //Start the connection
    $.connection.hub.start().done(function () {
    $('#sendmessage').click(function () {
    //Call the Hello method on the hub
    chat.server.hello($('#displayname').val(), $('#message').val());
    //Clear text box and reset focus for next comment
    $('#message').val('').focus();
    });
    });
    </script>
    </body>
    </html>

SignalR2Sendmessage.jpg

× 请我吃糖~
打赏二维码