SignalR學習筆記(三)Self-Host

SignalR能夠藉助Owin擺脫對IIS的依賴,實現Self-Host,使得SignalR有了部署在非Windows平臺的可能。javascript

 

什麼是Owin

Owin的英文全稱是Open Web Interface for .NET, 他定義了Web應用程序和Web服務器之間的接口。他的做用就是解除了Web應用程序與Web服務器之間的耦合,從而使Web應用程序再也不依賴於具體的Web服務器,已ASP.NET應用程序爲例,之前須要依賴於IIS,  引入Owin以後,他只依賴與Owin提供的接口,因此全部實現Owin接口的Web服務器均可以替換掉IIS。css

 

如何在控制檯程序中實現SignalR Self-Host

 

建立一個空的控制檯程序

 

引入SignalR SelfHost包

打開Package Manager Console面板,輸入如下命令安裝SignalR Self Host包。html

Install-package Microsoft.AspNet.SignalR.SelfHostjava

 

其餘可能須要引入的包

由於若是使用Self-Host, 一般會指定一個獨立的端口或者獨立ip,這樣就會出現跨域的問題,若是出現跨域問題,請引入Owin的CORS包jquery

Install-package Microsoft.Owin.Cors跨域

使用Owin啓動一個Web服務器

 

    class Program

    {

        static void Main(string[] args)

        {

            string url = "http://localhost:9021";

            using (WebApp.Start(url))

            {

                Console.WriteLine("Server running on {0}", url);

                Console.ReadKey();

            }

        }

}

 

 

添加Owin啓動類

 

 

    class Startup

    {

        public void Configuration(IAppBuilder app)

        {

            //容許全部域名跨域訪問

            app.UseCors(CorsOptions.AllowAll);

 

            //啓動SignalR

            app.MapSignalR();

        }

    }


 

 

添加Hub代碼

這裏咱們能夠直接把學習筆記(一)中的Hub代碼直接Copy過來,最終的的Self Host代碼以下服務器

 

 

using Microsoft.AspNet.SignalR;

using Microsoft.Owin.Cors;

using Microsoft.Owin.Hosting;

using Owin;

using System;

using System.Collections.Generic;

using System.Linq;

 

namespace SignalRSelfHost

{

    class Program

    {

        static void Main(string[] args)

        {

            string url = "http://localhost:9021";

            using (WebApp.Start(url))

            {

                Console.WriteLine("Server running on {0}", url);

                Console.ReadKey();

            }

        }

    }

 

    class Startup

    {

        public void Configuration(IAppBuilder app)

        {

            //容許全部域名跨域訪問

            app.UseCors(CorsOptions.AllowAll);

 

            //啓動SignalR

            app.MapSignalR();

        }

    }

 

    public class ChatRoomHub : Hub

    {

        private static Dictionary<string, string> _nickNames = new Dictionary<string, string>();

 

        public void SetNickName(string nickName)

        {

            //當Hub啓動完畢,每一個鏈接到這個Hub的客戶端都會自動分配一個惟一的ConnectionId。

            //當SignalR向指定客戶端推送消息的時候,須要指定ConnectionId, 因此這裏須要記錄一下每一個暱稱對應的客戶端ConnectionId

            _nickNames.Add(Context.ConnectionId, nickName);

 

            //當用戶設置暱稱以後,須要發送歡迎信息到全部的用戶客戶端,調用客戶端receiveWelcomeMessage方法顯示歡迎信息

            Clients.All.ReceiveWelcomeMessage($"{nickName}進入聊天室。");

        }

 

        public void Send(string nickName, string message)

        {

            if (string.IsNullOrWhiteSpace(nickName) || string.IsNullOrWhiteSpace(message))

            {

                //若是用戶暱稱或者消息不存在,就不作任何操做

                return;

            }

 

            if (message.StartsWith("to") && message.Split(' ').Length == 3)

            {

                //私聊消息

                var toUserName = message.Split(' ')[1];

 

                if (_nickNames.ContainsValue(toUserName))

                {

                    var connectionId = _nickNames.First(p => p.Value == toUserName).Key;

 

                    if (!string.IsNullOrWhiteSpace(connectionId) && connectionId != Context.ConnectionId)

                    {

                        Clients.Client(connectionId).ReceivePrivateMessage(nickName, message.Split(' ')[2]);

                    }

                }

            }

            else

            {

                //普通廣播消息

                if (_nickNames.ContainsValue(nickName))

                {

                    Clients.All.ReceiveBroadcastMessage(nickName, message);

                }

            }

        }

    }

}


 

運行程序

按Ctrl+F5啓動控制檯程序, 顯示Server running on xxxxx.代表服務器啓動成功。app

 

 

添加聊天室網頁

 

這裏須要從新建立一個空的Web程序學習

添加所需SignalR庫

由於SignalR服務器已經移到了控制檯程序當中,因此這裏不須要應用Microsft.AspNet.SignalR庫了ui

 

這裏僅須要引入SignalR的客戶端腳本

Install-package Microsoft.AspNet.SignalR.JS

 

添加聊天網頁

這裏咱們將學習筆記(一)的代碼直接copy過來,稍做修改。

  1. 原先咱們引用<script src="signalr/hubs"></script>須要替換爲<script src="http://localhost:9021/signalr/hubs"></script>
  2. 在建立Hub代理以前,須要設置SignalR服務器的地址

$.connection.hub.url = 'http://localhost:9021/signalr';

 

 

最終網頁代碼

 

 

<!DOCTYPE html>

<html>

<head>

    <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 src="Scripts/jquery-1.6.4.min.js"></script>

    <script src="Scripts/jquery.signalR-2.2.2.min.js"></script>

    <!--<script src="signalr/hubs"></script>-->

    <script src="http://localhost:9021/signalr/hubs"></script>

 

    <script type="text/javascript">

        $(function () {

 

            $.connection.hub.url = 'http://localhost:9021/signalr';

 

            //使用代理模式, 建立客戶端的hub代理

            var chat = $.connection.chatRoomHub;

 

            //服務器Hub中, 調用ReceiveWelcomeMessage方法時, 會執行客戶端的chat.client.receiveBroadcastMessage方法

            chat.client.receiveBroadcastMessage = function (name, message) {

 

                //防JS輸入

                var encodedName = $('<div />').text(name).html();

                var encodedMsg = $('<div />').text(message).html();

 

                $('#discussion').append('<li><strong>' + encodedName

                    + '</strong>:  ' + encodedMsg + '</li>');

            };

 

            //服務器Hub中, 調用ReceiveWelcomeMessage方法時, 會執行客戶端的chat.client.receiveWelcomeMessage方法

            chat.client.receiveWelcomeMessage = function (message) {

                var encodedMsg = $('<div />').text(message).html();

 

                $('#discussion').append('<li><strong style="color:blue">' + encodedMsg

                    + '</strong></li>');

            };

 

            //服務器Hub中, 調用ReceivePrivateMessage方法時, 會執行客戶端的chat.client.receivePrivateMessage方法

            chat.client.receivePrivateMessage = function (name, message) {

                var encodedName = $('<div />').text(name).html();

                var encodedMsg = $('<div />').text(message).html();

 

                $('#discussion').append('<li><strong style="color: green">' + encodedName

                    + '偷偷的跟你說</strong>:  ' + encodedMsg + '</li>');

            };

 

            //經過代理鏈接到服務器Hub

            $.connection.hub.start().done(function () {

                $('#sendmessage').click(function () {

                    chat.server.send($('#displayname').val(), $('#message').val());

 

                    $('#message').val('').focus();

                });

 

                //鏈接成功後, 須要用戶馬上輸入暱稱

                $('#displayname').val(prompt('Enter your name:', ''));

                chat.server.setNickName($('#displayname').val());

                $('#message').focus();

            });

        });

    </script>

</body>

</html>


 

 

啓動程序,效果以下

 

酷炫功能

使用Self-Host以後,咱們能夠實現一個很酷炫的功能,在控制檯程序中監控用戶的輸入

 

 

public class ChatRoomHub : Hub

    {

        private static Dictionary<string, string> _nickNames = new Dictionary<string, string>();

 

        public void SetNickName(string nickName)

        {

            //當Hub啓動完畢,每一個鏈接到這個Hub的客戶端都會自動分配一個惟一的ConnectionId。

            //當SignalR向指定客戶端推送消息的時候,須要指定ConnectionId, 因此這裏須要記錄一下每一個暱稱對應的客戶端ConnectionId

            _nickNames.Add(Context.ConnectionId, nickName);

 

            //當用戶設置暱稱以後,須要發送歡迎信息到全部的用戶客戶端,調用客戶端receiveWelcomeMessage方法顯示歡迎信息

            Clients.All.ReceiveWelcomeMessage($"{nickName}進入聊天室。");

            Console.WriteLine($"{nickName}進入聊天室。");

        }

 

        public void Send(string nickName, string message)

        {

            if (string.IsNullOrWhiteSpace(nickName) || string.IsNullOrWhiteSpace(message))

            {

                //若是用戶暱稱或者消息不存在,就不作任何操做

                return;

            }

 

            if (message.StartsWith("to") && message.Split(' ').Length == 3)

            {

                //私聊消息

                var toUserName = message.Split(' ')[1];

 

                if (_nickNames.ContainsValue(toUserName))

                {

                    var connectionId = _nickNames.First(p => p.Value == toUserName).Key;

 

                    if (!string.IsNullOrWhiteSpace(connectionId) && connectionId != Context.ConnectionId)

                    {

                        Clients.Client(connectionId).ReceivePrivateMessage(nickName, message.Split(' ')[2]);

                        Console.WriteLine($"{nickName}偷偷對{toUserName}說:{message}");

                    }

                }

            }

            else

            {

                //普通廣播消息

                if (_nickNames.ContainsValue(nickName))

                {

                    Clients.All.ReceiveBroadcastMessage(nickName, message);

                    Console.WriteLine($"{nickName}對你們說:{message}");

                }

            }

        }

    }

 

相關文章
相關標籤/搜索