SignalR能夠藉助Owin擺脫對IIS的依賴,實現Self-Host,使得SignalR有了部署在非Windows平臺的可能。javascript
Owin的英文全稱是Open Web Interface for .NET, 他定義了Web應用程序和Web服務器之間的接口。他的做用就是解除了Web應用程序與Web服務器之間的耦合,從而使Web應用程序再也不依賴於具體的Web服務器,已ASP.NET應用程序爲例,之前須要依賴於IIS, 引入Owin以後,他只依賴與Owin提供的接口,因此全部實現Owin接口的Web服務器均可以替換掉IIS。css
打開Package Manager Console面板,輸入如下命令安裝SignalR Self Host包。html
Install-package Microsoft.AspNet.SignalR.SelfHostjava
由於若是使用Self-Host, 一般會指定一個獨立的端口或者獨立ip,這樣就會出現跨域的問題,若是出現跨域問題,請引入Owin的CORS包jquery
Install-package Microsoft.Owin.Cors跨域
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(); } }
這裏咱們能夠直接把學習筆記(一)中的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服務器已經移到了控制檯程序當中,因此這裏不須要應用Microsft.AspNet.SignalR庫了ui
這裏僅須要引入SignalR的客戶端腳本
Install-package Microsoft.AspNet.SignalR.JS
這裏咱們將學習筆記(一)的代碼直接copy過來,稍做修改。
$.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}"); } } } }