SignalR快速入門 ~ 仿QQ即時聊天,消息推送,單聊,群聊,多群公聊(基礎=》提升,5個Demo貫徹全篇,感興趣的玩才是真的學)
官方demo:http://www.asp.net/signalr/overview/getting-started/tutorial-getting-started-with-signalr
應用情景之一:
沒太多連續的時間來研究SignalR,所以我把這篇文章分了三個階段:
第一個階段,簡單使用,熟悉並認識SignalR
第二個階段,實現上圖的單聊效果
第三個階段,實現類似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誕生,比昨天簡單多了
這個是逆天的自學筆記: