1. 程式人生 > >史上最全面的SignalR系列教程-4、SignalR 自託管全解(使用Self-Host)-附各終端詳細例項

史上最全面的SignalR系列教程-4、SignalR 自託管全解(使用Self-Host)-附各終端詳細例項

1、概述

通過前面幾篇文章

史上最全面的SignalR系列教程-1、認識SignalR

史上最全面的SignalR系列教程-2、SignalR 實現推送功能-永久連線類實現方式

史上最全面的SignalR系列教程-3、SignalR 實現推送功能-集線器類實現方式

我們對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的控制檯應用程式,如下所所示:

要使用Selft-Host宿主SignalR,必須引用Microsoft.AspNet.SignalR.SelfHost包。我們在程式包管理控制檯輸入以下命令安裝SelfHost包。

Install-Package Microsoft.AspNet.SignalR.SelfHost

要想支援跨域訪問,還需要安裝

Install-Package Microsoft.Owin.Cors

如果用命令的方式安裝失敗,我們可以用NuGet的方式安裝,如下圖所示。

編寫程式碼如下:

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控制檯服務端如下。

可以看到我們的控制檯服務端已經成功啟動起來了。

3、用javascript客戶端訪問SignalR Self-Host服務端

3.1、新建SignalRSelfHostJSClient的MVC空專案

3.2、新增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="width: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控制檯服務端後,再執行兩個我們的測試客戶端,分別輸入不同的使用者名稱,試試聊天的效果,如下圖所示。

4、用WinForm客戶端接收SignalR Self-Host服務端訊息

4.1、新建SignalRSelfHost的WinForm專案

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

4.3、製作測試介面如下:

編寫介面程式碼如下:

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}\r\n",ServerUrl));
                }
                else
                {
                    msgContent.AppendText("與伺服器連線失敗,請確認伺服器是否開啟。\r\n");
                }
            }).Wait();
        }

        private void Connection_Closed()
        {
            msgContent.AppendText("連線關閉...\r\n");
        }

        private void RecvMsg(string name, string message)
        {
            msgContent.AppendText(string.Format("接收時間:{0},傳送人:{1},訊息內容:{2},\r\n", DateTime.Now, name, message));          
        }
    }
}

4.4、執行效果:

通過以上的詳細講解,我們已經非常清楚的瞭解瞭如何通過SignalR打通各終端以實現相互溝通的通訊。例子雖然比較簡潔,但完全可以以此為基礎,擴充套件更復雜的業務應用。

5、程式碼下載

例項原始碼可以移步github下載,地址:https://github.com/yonghu86/SignalRTestProj

6、參考文章

  • 史上最全面的SignalR系列教程-1、認識SignalR

  • 史上最全面的SignalR系列教程-2、SignalR 實現推送功能-永久連線類實現方式

  • 史上最全面的SignalR系列教程-3、SignalR 實現推送功能-集線器類實現方式

  • Real-time ASP.NET with SignalR

  • 微信公眾號開發系列-玩轉微信開發-目錄彙總

  • RDIFramework.NET — 基於.NET的快速資訊化系統開發框架 — 系列目錄

  • RDIFramework.NET ━ .NET快速資訊化系統開發框架 ━ 工作流程元件介紹

  • RDIFramework.NET框架SOA解決方案(集Windows服務、WinForm形式與IIS形式釋出)-分散式應用

  • RDIFramework.NET程式碼生成器全新V3.5版本釋出-重大升級


一路走來數個年頭,感謝RDIFramework.NET框架的支持者與使用者,大家可以通過下面的地址瞭解詳情。

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

RDIFramework.NET官方部落格:http://blog.rdiframework.net/

同時需要說明的,以後的所有技術文章以官方網站為準,歡迎大家收藏!

RDIFramework.NET框架由海南國思軟體科技有限公司專業團隊長期打造、一直在更新、一直在升級,請放心使用!

歡迎關注RDIFramework.net框架官方公眾微信(微訊號:guosisoft),及時瞭解最新動態。

掃描二維碼立即關注