zoukankan      html  css  js  c++  java
  • 史上最全面的SignalR系列教程-4、SignalR 自托管全解(使用Self-Host)-附各终端详细实例

    1、概述

    通过前面几篇文章

    史上最全面的SignalR系列教程-1、认识SignalR

    史上最全面的SignalR系列教程-2、SignalR 实现推送功能-永久连接类实现方式

    史上最全面的SignalR系列教程-3、SignalR 实现推送功能-集线器类实现方式

    RDIFramework.NET敏捷开发框架通过SignalR技术整合即时通讯(IM)

    我们对SignalR的概念以及SignalR的最主要的两类通信模型(Persistent Connections与Hubs)进行了详细的对比讲解,也做了案例展示。本篇将为大家介绍.NET特有的Self-Host自托管的应用,即以Self-Host自托管为宿主加载SignalR服务。

    宿主一词我们不会陌生,它可以看作是一个基础设施,它为一些服务和功能提供最底层的支持,如你的web应用程序可以运行在iis或者apache上,而这两个东西就是web应用程序的宿主,而今天说的自主宿主SelfHost它可以自己去监听自己的服务,如你可以把一个web应用程序宿主到一个console控制台程序上,或者把一个webApi宿主到一个console或者windowService上,这都是可以的。

    Self-Host的介绍我们可以参考msdn官方事例https://docs.microsoft.com/en-us/dotnet/framework/wcf/samples/self-host 这是一个wcf的事例。

    SignalR常常依托于ASP.NET应用程序运行于IIS中,但它还可以自我托管(比如作为console winform、Windows service),只要我们使用self-host库就可以了。该库向所有的SignalR 2库一样,构建于OWIN (Open Web Interface for .NET)。OWIN定义了一个在.NET web 服务端和web 应用程序的抽象。OWIN解耦了从服务端来的web 应用程序,这使得OWIN对于子托管web应用程序于自己的进程中得以表现得很完美。

    有的小伙伴可能就要问了,为什么一定要使用这种方式来托管呢?基于IIS的方式不是更简单吗?不托管于IIS的原因主要有以下方面的考虑:

    • 我们已经构建了一个服务端程序,没有运行在IIS上,重新搭建成本太高。
    • IIS的方式性能开销很大。
    • signalR需要扩展到现有程序中,如Windows服务中等。
    • 其他的一些原因....

    本篇主要讲解以下内容:

    1. 使用Self-Host方式创建SignalR服务端
    2. 用javascript客户端访问SignalR Self-Host服务端
    3. 用WinForm客户端接收SignalR Self-Host服务端消息

    2、使用Self-Host方式创建SignalR服务端

    为了更简单的说明self-host托管的方式,我们用控制台应用程序来做演示。当然我们也可以自托管到Windows服务中去,如果你更希望托管到Windows服务,可以参考Self-Hosting SignalR in a Windows Service

    在上一项目的基础上,我们新建一个名为:SignalRSelfHost的控制台应用程序,如下所所示:

    新建SignalRSelfHost控制台应用程序

    要使用Selft-Host宿主SignalR,必须引用Microsoft.AspNet.SignalR.SelfHost包。我们在程序包管理控制台输入以下命令安装SelfHost包。

    Install-Package Microsoft.AspNet.SignalR.SelfHost
    

    要想支持跨域访问,还需要安装

    Install-Package Microsoft.Owin.Cors
    

    如果用命令的方式安装失败,我们可以用NuGet的方式安装,如下图所示。
    NuGet方式安装Self-Host

    NuGet方式安装Self-Host

    编写代码如下:

    using Microsoft.AspNet.SignalR;
    using Microsoft.Owin.Cors;
    using Microsoft.Owin.Hosting;
    using Owin;
    using System;
    
    namespace SignalRSelfHost
    {
        class Program
        {
            static void Main(string[] args)
            {
                // This will *ONLY* bind to localhost, if you want to bind to all addresses
                // use http://*:8080 to bind to all addresses. 
                // See http://msdn.microsoft.com/en-us/library/system.net.httplistener.aspx 
                // for more information.
                string url = "http://localhost:8077";
                using (WebApp.Start(url))
                {
                    Console.WriteLine("SignalR Server running on {0}", url);
                    Console.ReadLine();
                }
            }
        }
    
        /// <summary>
        /// 该类含有SignalR服务端的配置(该教程使用的唯一的配置是用来调用UseCors), 
        /// MapSignalR为所有形式的Hub对象创建了路由规则
        /// </summary>
        class Startup
        {
            public void Configuration(IAppBuilder app)
            {
                app.UseCors(CorsOptions.AllowAll);
                app.MapSignalR();
            }
        }
    
        /// <summary>
        /// SignalR的Hub 类是程序要提供给客户端的
        /// 该类就一个方法,Send:客户端可以用来发送消息给其他客户端
        /// </summary>
        public class MyHub : Hub
        {
            //服务端的方法,客户端可以去调用
            public void Send(string name, string message)
            {
                //调用客户端的方法addMessage(string s1,string s2);      
                Clients.All.addMessage(name, message);
            }
        }
    }
    

    代码说明:

    • Program:包含程序的主方法。在这个方法中,类型为Startup的web应用程序启动于指定的URL (http://localhost:8077)。 如果需要更加安全一点,可以支持SSL,请去这里看看How to: Configure a Port with an SSL Certificate

    • Startup: 该类含有SignalR服务端的配置(该教程使用的唯一的配置是用来调用UseCors), MapSignalR为所有形式的Hub对象创建了路由规则。

    • MyHub:SignalR的Hub 类是程序要提供给客户端的。 该类就一个方法:Send, 客户端可以用来发送消息给其他客户端。

    编译运行SignalR控制台服务端如下。

    SignalR控制台服务端启动

    可以看到我们的控制台服务端已经成功启动起来了。

    3、用javascript客户端访问SignalR Self-Host服务端

    3.1、新建SignalRSelfHostJSClient的MVC空项目

    新建SignalRSelfHostJSClient的MVC空项目

    3.2、添加Microsoft.AspNet.SignalR.JS的引用

    添加Microsoft.AspNet.SignalR.JS的引用

    3.3、新建Default.html页面

    代码如下:

    <!DOCTYPE html>
    <html>
    <head>
        <title>SignalRSelfHostJSClient Chat</title>
        <style type="text/css">
            .container {
                background-color: #a1c6ec;
                border: thick solid #e62fc7;
                padding: 20px;
                margin: 20px;
            }
        </style>
    </head>
    <body>
        <div class="container">
            <input type="text" id="message" style="350px;" placeholder="请输入消息内容..."/>
            <input type="button" id="sendmessage" value="发送" />
            <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.4.1.min.js"></script>
        <!--Reference the autogenerated SignalR hub script. -->
        <script src="http://localhost:8077/signalr/hubs"></script>
        <!--Add script to update the page and send messages.-->
        <script type="text/javascript">
            $(function () {
                //Set the hubs URL for the connection
                $.connection.hub.url = "http://localhost:8077/signalr";
                // Declare a proxy to reference the hub.
                var chat = $.connection.myHub;
    
                // Create a function that the hub can call to broadcast messages.
                chat.client.addMessage = 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').prepend('<li><strong>' + encodedName
                        + '</strong>:&nbsp;&nbsp;' + encodedMsg + '</li>');
                };
                // Get the user name and store it to prepend to messages.
                $('#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 Send method on the hub.
                        chat.server.send($('#displayname').val(), $('#message').val());
                        // Clear text box and reset focus for next comment.
                        $('#message').val('').focus();
                    });
                });
            });
        </script>
    </body>
    </html>
    

    3.4、运行效果

    先运行SignalRSelfHost控制台服务端后,再运行两个我们的测试客户端,分别输入不同的用户名,试试聊天的效果,如下图所示。

    SignalRSelfHostJSClient运行效果

    4、用WinForm客户端接收SignalR Self-Host服务端消息

    4.1、新建SignalRSelfHost的WinForm项目

    新建SignalRSelfHost的WinForm项目

    4.2、使用NuGet安装Microsoft.AspNet.SignalR.Client包

    NuGet安装Microsoft.AspNet.SignalR.Client包

    4.3、制作测试界面如下:

    SignalRWinForm测试客户端设计界面

    编写界面代码如下:

    using Microsoft.AspNet.SignalR.Client;
    using System;
    using System.Configuration;
    using System.Windows.Forms;
    
    namespace SignalRSelfHostWinFormClient
    {
        /// <summary>
        /// SignalRSelfHost WinForm测试客户端
        /// 用于接收消息(需配合SignalRSelfHostJSClient项目使用)
        /// </summary>
        public partial class SignalRSelfHostWinFormClientTest : Form
        {
            //定义代理,广播服务连接相关
            private static IHubProxy HubProxy { get; set; }
            private static readonly string ServerUrl = ConfigurationManager.AppSettings["SignalRServer"];
            //定义一个连接对象
            public static HubConnection Connection { get; set; }
    
            public SignalRSelfHostWinFormClientTest()
            {
                CheckForIllegalCrossThreadCalls = false;
                InitializeComponent();
            }
    
            private void SignalRSelfHostWinFormClientTest_Load(object sender, EventArgs e)
            {
                Connection = new HubConnection(ServerUrl);            
                Connection.Closed += Connection_Closed;
                HubProxy = Connection.CreateHubProxy("MyHub");
                HubProxy.On<string, string>("addMessage", RecvMsg);//接收实时信息
                Connection.Start().ContinueWith(task =>
                {
                    if (!task.IsFaulted)
                    {
                        msgContent.AppendText(string.Format("与Signal服务器连接成功,服务器地址:{0}
    ",ServerUrl));
                    }
                    else
                    {
                        msgContent.AppendText("与服务器连接失败,请确认服务器是否开启。
    ");
                    }
                }).Wait();
            }
    
            private void Connection_Closed()
            {
                msgContent.AppendText("连接关闭...
    ");
            }
    
            private void RecvMsg(string name, string message)
            {
                msgContent.AppendText(string.Format("接收时间:{0},发送人:{1},消息内容:{2},
    ", DateTime.Now, name, message));          
            }
        }
    }
    

    4.4、运行效果:

    SignalRWinForm测试客户端运行效果

    通过以上的详细讲解,我们已经非常清楚的了解了如何通过SignalR打通各终端以实现相互沟通的通信。例子虽然比较简洁,但完全可以以此为基础,扩展更复杂的业务应用。

    5、代码下载

    实例源码可以移步github下载,地址:https://github.com/yonghu86/SignalRTestProj

    6、参考文章


    一路走来数个年头,感谢RDIFramework.NET框架的支持者与使用者,大家可以通过下面的地址了解详情。

    RDIFramework.NET官方网站:http://www.rdiframework.net/

    RDIFramework.NET官方博客:http://blog.rdiframework.net/

    同时需要说明的,以后的所有技术文章以官方网站为准,欢迎大家收藏!

    RDIFramework.NET框架由海南国思软件科技有限公司专业团队长期打造、一直在更新、一直在升级,请放心使用!

    欢迎关注RDIFramework.net框架官方公众微信(微信号:guosisoft),及时了解最新动态。

    扫描二维码立即关注

    微信号:guosisoft

  • 相关阅读:
    expandablelistview学习在listView里面嵌套GridView
    App数据格式之解析Json
    不应和应该在SD卡应用应用
    9 个用来加速 HTML5 应用的方法
    Android设计模式系列-索引
    ObjectiveC语法快速参考
    App列表显示分组ListView
    进程、线程和协程的图解
    Python多进程原理与实现
    Python多线程的原理与实现
  • 原文地址:https://www.cnblogs.com/huyong/p/11381349.html
Copyright © 2011-2022 走看看