65.9K
CodeProject 正在变化。 阅读更多。
Home

ASP.NET SignalR 基础知识循序渐进(第一部分)

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.71/5 (18投票s)

2013年8月7日

CPOL

4分钟阅读

viewsIcon

154632

downloadIcon

7111

识别并学习使用 SignalR 基础

引言

在本篇文章中,我将介绍我最近学习到的 ASP.NET SignalR 的非常基础的知识,并通过一个最简单的示例(SignalREcho_no_packages.zip)来逐步演示,该示例使用了 PersistentConnection 。请注意,我已从解决方案中删除了 packages 文件夹,因为上传大小太大。您可以通过 NuGet 在本地获取 Microsoft.AspNet.SignalR 进行构建。好的,让我们从一些基本问题开始。

ASP.NET SignalR 可以做什么?

  • 服务器通过 HTTP 连接将数据推送到客户端
  • 服务器到客户端的 RPC(远程过程调用)在 HTTP 连接中
  • 通过 SQL Server、Redis 或 Service Bus 轻松扩展

SignalR 使用什么技术来传输数据?

  • 如果可用,则使用 WebSockets
  • 否则,使用其他技术,例如长轮询

SignalR 支持传输什么类型的数据?

  • 未压缩的 JSON 文本或纯文本
  • 如果您想传输压缩的 JSON、BSON 或二进制数据,则需要对数据进行编码和解码(例如使用 Base64),或者在服务器端实现自定义逻辑的 IJsonSerializer ,并在客户端实现相同的逻辑。请注意,SignalR 内部使用了 TextReader TextWriter 。这意味着您无论如何都必须在传输之前将数据转换为文本。

当前稳定版本是 1.1.3。2.0 版本处于 Beta 阶段。许可证是 Apache 2.0。官方网站是 http://signalr.net。文档可以在 这里 找到。

软件包

所有 SignalR 开发包都可以通过 NuGet 获取。通常,您只需要获取 Microsoft.AspNet.SignalR(包 ID),它包含了您需要的大部分组件,包括:

  • Microsoft.AspNet.SignalR.Core:用于构建 SignalR 端点的服务器端组件。
  • Microsoft.AspNet.SignalR.Owin:SignalR 的 OWIN 宿主。
  • Microsoft.AspNet.SignalR.SystemWeb:用于在 ASP.NET 中宿主 SignalR(通过 OWIN ASP.NET 宿主)。
  • Microsoft.AspNet.SignalR.Js:SignalR 的 JavaScript 客户端。
  • 依赖项也包含在内:jQuery、Newtonsoft.JsonMicrosoft.Owin.Host.SystemWebMicrosoft.Web.Infrastructure 和 OWIN。

您可以根据需要获取其他 SignalR 包:

  • Microsoft.AspNet.SignalR.Client:SignalR 的 .NET 客户端(包括 WinRT、WP8 和 Silverlight5)。
  • Microsoft.AspNet.SignalR.Redis:用于在 Web 场中扩展 SignalR 的 Redis 消息传递后备。
  • Microsoft.AspNet.SignalR.ServiceBus:用于在 Web 场中扩展 SignalR 的 Windows Azure Service Bus 消息传递后备。
  • Microsoft.AspNet.SignalR.SqlServer:用于在 Web 场中扩展 SignalR 的 SQL Server 消息传递后备。
  • Microsoft.AspNet.SignalR.Sample:用于在您的应用程序中快速设置一个可运行的示例。

PersistentConnection

PersistentConnection 是用于在服务器端宿主 SignalR 服务的核心类。我将演示如何使用它。

首先,我创建一个新的 ASP.NET Web 应用程序,并使用 NuGet 获取 Microsoft.AspNet.SignalR 包。然后,我定义一个继承自 PersistentConnection 的新类。

public class MyConnection : PersistentConnection 
{
    protected override Task OnConnected(IRequest request, string connectionId)
    {
        string msg = string.Format(
            "A new user {0} has just joined. (ID: {1})",  
            request.QueryString["name"], connectionId);
        return Connection.Broadcast(msg);
    }
    protected override Task OnReceived(IRequest request, string connectionId, string data)
    {
        // Broadcast data to all clients
        string msg = string.Format(
            "{0}: {1}", request.QueryString["name"], data);
        return Connection.Broadcast(msg);
    }
}

当客户端连接到我的服务时,会调用 OnConnected 。连接通过连接 ID(GUID)进行区分。客户端可以在建立连接时通过 IRequest.QueryString 传递一些信息。我们还可以从 IRequest 获取其他 HTTP 项,如 cookie、提交的表单、标头和用户主体。请注意,所有这些项都属于请求建立连接的第一个请求。

当客户端数据到达时,会调用 OnReceived connectionId 指示数据来自哪个连接。数据以文本格式传输。如果数据不代表纯文本,您需要自行解析。

PersistentConnection.Connection 提供了 Broadcast 方法将消息发送给所有已连接的客户端;它还提供了 Send 方法将消息发送给特定连接或组(使用组名作为 connectionId)。两种方法都支持一个排除列表,用于指定不希望发送消息到的连接。

我们可以在 Global.asax 中使用 MyConnection 将我们的服务注册到路由表中。

public class Global : System.Web.HttpApplication 
{
    protected void Application_Start(object sender, EventArgs e)
    {
        RouteTable.Routes.MapConnection<MyConnection>("echo", "/echo");
    }
} 

现在我们可以编写网页中的 JavaScript 来连接到我们的服务。

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head> 
    <title>SignalR Echo</title>
    <script type="text/javascript" src="Scripts/jquery-2.0.3.min.js"></script>   
    <script type="text/javascript" src="Scripts/jquery.signalR-1.1.3.min.js"></script>
</head>
<body>
    <script type="text/javascript">
        function htmlEncode(value) {
            return $("<div/>").text(value).html();
        }
        
        function addMsg(msg) {
            $("#messages").append("<li>" + htmlEncode(msg) + "</li>");
        }
        $(function () {
            $("#join").click(function () {
                var connection = $.connection("/echo", "name=" + $("#name").val(), true);;
                
                connection.received(function (data) {
                    addMsg(data);
                });
                connection.error(function (err) {
                    addMsg("Error: " + err);
                });
            
                addMsg("Connecting...");
                connection.start(function () {
                    addMsg("Connected.");
                    $("#send").click(function () {
                        connection.send($("#msg").val());
                    });
                });
            });
        });
    </script>
    <table>
        <tr>
            <td><span>Name:</span></td>
            <td><input type="text" id="name" /></td>
            <td><input type="button" value="Join" id="join" /></td>
        </tr>
        <tr>
            <td><span>Message:</span></td>
            <td><input type="text" id="msg" /></td>
            <td><input type="button" value="Send" id="send" /></td>
        </tr>
    </table>
    <ul id="messages"></ul>
</body>
</html>  

接下来,让我们创建一个 .NET 客户端。只需创建一个新的控制台应用程序,并使用 NuGet 获取 Microsoft.AspNet.SignalR.Client 包。在 Main 函数中,我使用 Connection 类与我们的服务进行通信。

class Program  
{
    private const string ServiceUri = "https://:12722/echo";
    static void Main(string[] args) 
    {
        var connection = new Connection(ServiceUri, "name=dzy");
        connection.Received += connection_Received;
        connection.StateChanged += connection_StateChanged;
        Console.WriteLine("Connecting...");
        connection.Start().Wait();
        string inputMsg;
        while (!string.IsNullOrEmpty(inputMsg = Console.ReadLine()))
        {
            connection.Send(inputMsg).Wait();
        }
        connection.Stop();
    }
    static void connection_StateChanged(StateChange state)
    {
        if (state.NewState == ConnectionState.Connected)
        {
            Console.WriteLine("Connected.");
        }
    }
    static void connection_Received(string data)
    { 
        Console.WriteLine(data);
    }
} 

要查看服务是在 WebSockets 还是长轮询模式下运行,我们可以在 Windows 8 或 Windows Server 2012 上的 IIS 7.5 和 IIS 8.0 上宿主该服务。请注意,.NET WebSockets 仅在 Windows 8、Windows Server 2012 及以上版本上运行。然后,我们可以使用 Fiddler 检查客户端机器上的 HTTP 请求。

如果服务在 IIS 7.5 上宿主,连接请求会保持活动状态。

如果服务在 Windows 8 或 Windows Server 2012 的 IIS 8 上宿主,连接请求会要求升级到 WebSocket 连接。

摘要

在下一部分,我将介绍 SignalR Hubs、横向扩展和可扩展性。

© . All rights reserved.