SignalR快速入門 ~ 仿QQ即時聊天,消息推送,單聊,羣聊,多羣公聊(基礎=》提高,5個Demo貫徹全篇,感興趣的玩纔是真的學)javascript
官方demo:http://www.asp.net/signalr/overview/getting-started/tutorial-getting-started-with-signalrcss
應用情景之一:前端
沒太多連續的時間來研究SignalR,因此我把這篇文章分了三個階段:java
第一個階段,簡單使用,熟悉並認識SignalRjquery
第二個階段,實現上圖的單聊效果web
第三個階段,實現相似QQ羣發的功能瀏覽器
擴展階段,若是有時間,逆天會再開一篇,封裝一個LoTSignalR,看過逆天封裝的人都知道,絕對簡單又輕量級服務器
好比LoTQQ,如今已經不少人在用了,後期會添加新功能,敬請期待~~架構
++++++++++++++++++ 我是華麗的分割線 +++++++++++++++++++++
步入正軌:
第一個階段:
1.什麼是ASP.NET SignalR?
ASP .NET SignalR是一個 ASP .NET 下的類庫,能夠在ASP .NET 的Web項目中實現實時通訊。什麼是實時通訊的Web呢?就是讓客戶端(Web頁面)和服務器端能夠互相通知消息及調用方法,固然這是實時操做的。
WebSockets是Html5提供的新的API,能夠在Web網頁與服務器端間創建Socket鏈接,當WebSockets可用時(即瀏覽器支持Html5)SignalR使用WebSockets,當不支持時SignalR將使用其它技術來保證達到相同效果。
SignalR固然也提供了很是簡單易用的高階API,使服務器端能夠單個或批量調用客戶端上的JavaScript函數,而且很是 方便地進行鏈接管理,例如客戶端鏈接到服務器端,或斷開鏈接,客戶端分組,以及客戶端受權,使用SignalR都很是 容易實現。
2.可使用ASP.NET SingalR作什麼?
SignalR 將與客戶端進行實時通訊帶給了ASP .NET 。固然這樣既好用,並且也有足夠的擴展性。之前用戶須要刷新頁面或使用Ajax輪詢才能實現的實時顯示數據,如今只要使用SignalR,就能夠簡單實現了。最重要的是您無需從新創建項目,使用現有ASP .NET項目便可無縫使用SignalR。
網上某架構圖:
上面亂七八糟的估計不少人懶得看,好吧,你能夠這樣理解:
使用了SignalR就可讓客戶端經過SignalR代理直接調用服務端的方法,讓服務端經過SignalR直接調用客戶端的方法
下面咱們來實例演示一下,先演示一下不用IIS的狀況:
新建一個控制檯項目,引入 signalR Self Host (能夠思考一下爲何會用NuGet包,他到底好在哪?O(∩_∩)O~不清楚等項目演示完你應該就知道了)
這是他的依賴項
安裝一下Owin.Cors
依賴項:
新增一個Owin的Startup類,相似於咱們傳統項目的Global文件
註冊一下signalR中間組件(學過mvc的能夠變相的理解爲註冊路由之類的)
在main方法中綁定端口(不必定是8080,好比我demo中就用的其餘端口)
建立一個「SignalR集線器」(控制檯這邊由於沒有集線器因此只能本身建類)
建了一個DntHub,定義了一個服務器端的方法,叫ServiceSend(一會會用到)
轉到定義,看看Hub類(好東西啊,還有分組啥的,下面會講)
運行一下,若是出錯請參考個人這篇文章:http://www.cnblogs.com/dunitian/p/5232229.html
先看看共引用多少dll(和MVC之類的比起是否是簡潔不少?一會演示好處在哪)最小引用
建立一個web的Client,引用一下 SignalR的js包,其實你會發現就是多了幾個js包並無引用任何dll(必須的,否則豈不是太臃腫?)
前端的調用步驟:
<!-- 總結一下: 1.先引入jq包,再引入signalR的js包,再引入signalR動態生成的hubs 2.設置signalR的hubs url地址:$.connection.hub.url =xxx 3.聲明一個代理對象來引用集線器:var chat = $.connection.dntHub; 4.建立一個客戶端方法:chat.client.xxxx=function(){} 5.啓動並調用服務端方法: $.connection.hub.start().done(function(){ chat.server.xxx() }); -->代碼貼起:
View Code<!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title>簡單聊天程序</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.8.3.min.js"></script> <script src="Scripts/jquery.signalR-2.2.0.js"></script> <!--動態生成的--> <script src="http://localhost:5438/signalr/hubs"></script> <script type="text/javascript"> $(function () { //日記記錄 $.connection.hub.logging = true; //設置hubs的url $.connection.hub.url = "http://localhost:5438/signalr"; // 聲明一個代理來引用該集線器。 var chat = $.connection.dntHub; // 建立一個方法供服務端調用 chat.client.addMessage = function (name, message) { var encodedName = $('<div />').text(name).html(); var encodedMsg = $('<div />').text(message).html(); $('#discussion').append('<li><strong>' + encodedName + '</strong>: ' + encodedMsg + '</li>'); }; $('#displayname').val('路人'); // 啓動 connection $.connection.hub.start().done(function () { $('#sendmessage').click(function () { //調用服務器端方法 chat.server.serviceSend($('#displayname').val(), $('#message').val()); }); }); }); </script> <!-- 總結一下: 1.先引入jq包,再引入signalR的js包,再引入signalR動態生成的hubs 2.設置signalR的hubs url地址:$.connection.hub.url =xxx 3.聲明一個代理對象來引用集線器:var chat = $.connection.dntHub; 4.建立一個客戶端方法:chat.client.xxxx=function(){} 5.啓動並調用服務端方法: $.connection.hub.start().done(function(){ chat.server.xxx() }); --> </body> </html>若是要調試的話,保證服務端先運行,調試小技巧:
下面說一下上面的好處:
webclient我就單獨拿出來了(一個js包,一個index.html),控制檯的程序我也單獨拿出來了,下面先運行一下服務端,再打開index.html
再次驗證最上面說的,端口不固定
QQ聊天案例,先講一種常規的方法,下面會講一種簡單方法
先看看gif效果圖把
定義一個BaseHub類,裏面用 qqModeList來臨時存放數據(用戶數據)
QQModel,目前就用到兩個屬性,其餘的能夠本身擴展
定義了一個上線方法,一會每一個客戶端都會調用(原本是準備用OnConnected的,沒辦法他沒參數。。。並且這個時候,qq暱稱尚未產生,因而我取其次的方案)
定義一個發消息的方法
下面就是前端的東西了,註釋很詳細,不清楚能夠直接留言,我沒高興深度封裝,主要就是簡單演示一下
代碼貼上:
客戶端-逆天
View Code<!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title>仿QQ聊天--我是逆天</title> <link href="Style/MyQQ.css" rel="stylesheet" /> </head> <body> <div><input id="inputMsg" /><input id="btn" type="button" value="發消息" /></div><br /><br /> <div id="main"></div> <script src="Scripts/jquery-2.2.1.min.js"></script> <script src="Scripts/jquery.signalR-2.2.0.min.js"></script> <script src="http://localhost:5438/signalr/hubs"></script> <script type="text/javascript"> $(function () { var leftHtml = [ '<div class="sender">', '<div><img src="http://img.jfdown.com/jfdown/201403/ygald3wajct.jpg"></div>', '<div><div class="left_triangle"></div>', '<span>{msg}</span></div></div>' ].join(''); var rightHtml = [ '<div class="receiver">', '<div><img src="http://tb.himg.baidu.com/sys/portrait/item/306c9328?t=1397975854"></div>', '<div><div class="right_triangle"></div>', '<span>{msg}</span></div></div>' ].join(''); //設置hubs的url $.connection.hub.url = 'http://localhost:5438/signalR'; // 聲明一個代理 var qqProxy = $.connection.qQHub; // 建立一個方法供服務端調用 qqProxy.client.sendMsg = function (msg) { $('#main').append(leftHtml.replace('{msg}', msg)); } // 啓動 connection $.connection.hub.start().done(function () { qqProxy.server.online('逆天');//QQ暱稱 $('#btn').click(function () { //獲取輸入 var qqmsg = $('#inputMsg').val(); //給逆天發消息 qqProxy.server.serviceSend('妹子', qqmsg); $('#main').append(rightHtml.replace('{msg}', qqmsg)); }); }); }); </script> </body> </html>客戶端-美女
View Code<!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title>仿QQ聊天--我是美女</title> <link href="Style/MyQQ.css" rel="stylesheet" /> </head> <body> <div><input id="inputMsg" /><input id="btn" type="button" value="發消息" /></div><br /><br /> <div id="main"></div> <script src="Scripts/jquery-2.2.1.min.js"></script> <script src="Scripts/jquery.signalR-2.2.0.min.js"></script> <script src="http://localhost:5438/signalr/hubs"></script> <script type="text/javascript"> $(function () { var rightHtml = [ '<div class="sender">', '<div><img src="http://img.jfdown.com/jfdown/201403/ygald3wajct.jpg"></div>', '<div><div class="left_triangle"></div>', '<span>{msg}</span></div></div>' ].join(''); var leftHtml = [ '<div class="receiver">', '<div><img src="http://tb.himg.baidu.com/sys/portrait/item/306c9328?t=1397975854"></div>', '<div><div class="right_triangle"></div>', '<span>{msg}</span></div></div>' ].join(''); //設置hubs的url $.connection.hub.url = 'http://localhost:5438/signalR'; // 聲明一個代理 var qqProxy = $.connection.qQHub; // 建立一個方法供服務端調用 qqProxy.client.sendMsg = function (msg) { $('#main').append(leftHtml.replace('{msg}', msg)); } // 啓動 connection $.connection.hub.start().done(function () { qqProxy.server.online('妹子');//QQ暱稱 $('#btn').click(function () { //獲取輸入 var qqmsg = $('#inputMsg').val(); //給逆天發消息 qqProxy.server.serviceSend('逆天', qqmsg); $('#main').append(rightHtml.replace('{msg}', qqmsg)); }); }); }); </script> </body> </html>
羣發
咱們先接着昨天的QQ聊天來講
此次用一個簡單的方法搞定
一個鍵值對集合存放ConnectionId和GroupName
每一個客戶端鏈接的時候會加入一個組
斷開的時候退出組發消息前端也進行了優化。ok,signalR第三個demo誕生,比昨天簡單多了
這個是逆天的自學筆記: