因為項目需要,需要在網(wǎng)頁上實現(xiàn)消息的推送。在百度上搜索了一下,發(fā)現(xiàn)實現(xiàn)網(wǎng)頁上的消息推送,可以使用asp.net 中的SignalR類庫,當然也可以使用H5的WebSocket Ajax的輪回。當然此處我們使用asp.net 中的SignalR類庫。因為它可以實現(xiàn)網(wǎng)頁上消息的實時推送。什么是實時推送呢,我簡單的說一下我個人的理解吧。實時:在同一時間類發(fā)生的事情,當然在計算機中并不是絕對的實時,因為CPU在同一時間片只能處理一個任務(wù),那么這個時候疑問又來了?
我們平時使用電腦又上網(wǎng),又聽音樂是如何實現(xiàn)的呢,因為現(xiàn)在的CPU的計算速度很快。CPU會把處理不同的任務(wù)的時間片,CPU會把時間片劃到很小,很小,小到我們?nèi)祟惛兄坏健1热缭诂F(xiàn)在這個時間片上,CPU正在處理音樂任務(wù),在下一個時間片的時候,CPU又在處理上網(wǎng)任務(wù)。所以我認為在計算機并沒有絕對的實時,只是我們?nèi)祟惛兄坏搅T了。
推送:在此處的推送是指在網(wǎng)頁消息推送。例如:用戶A和B分別在各自的電腦打開打開一個相同的消息推送網(wǎng)頁。假設(shè)用戶A現(xiàn)在向用戶B發(fā)送消息。就要經(jīng)歷一個這樣的過程 用戶A->Server->用戶B。當然具體的底層實現(xiàn)過程,我就不在些探討了哈。因為這個不是現(xiàn)在所要探討的主題。因為Server有地址一般是固定不變的。所以客戶端向服務(wù)器發(fā)送消息比較容易,因為目的地址固定。那服務(wù)器如何向客戶端發(fā)送消息呢,這個就有點難道了因為客戶端的地址不固定的,并且http是無狀態(tài)的是不能記住用戶的地址的。
所以為了解決這一個問題,計算機的先輩們用到了幾個方法:
1、客戶端"心跳"。每隔一段時間去訪問服務(wù)器,看看服務(wù)器有沒有任務(wù)給其客戶端。Ajax的輪回就是使用的這個方法。缺點就是實時性不太高。
2、服務(wù)端和客戶端的長連接,本文所要談到的SignalR就是用的這種思想。缺點:服務(wù)器的壓力大。
好了,現(xiàn)在就說一下什么是SignalR吧。SignalR 是為 ASP.NET 開發(fā)人員提供的一個庫,可以簡化開發(fā)人員將實時 Web 功能添加到應(yīng)用程序的過程。實時 Web 功能是指這樣一種功能:當所連接的客戶端變得可用時服務(wù)器代碼可以立即向其推送內(nèi)容,而不是讓服務(wù)器等待客戶端請求新的數(shù)據(jù)。這個也就實現(xiàn)消息的實時推送。我個人理解的實現(xiàn)原理是首先由服務(wù)器定制一個函數(shù)用于一個客戶端調(diào)用將消息發(fā)送給另一個客戶端。當然客戶端也需要定抽一個函數(shù)。因為服務(wù)器需要調(diào)用客戶端的這個函數(shù)。
下面就說下具體的操作方法吧。
1、環(huán)境:win 10+VS2015 社區(qū)版
我使用asp.net mvc。首先打開VS 2015|文件|新建|項目(SignalRMvc)|asp.net Web應(yīng)用程序|空模板,MVC,平臺大概就是這樣了。
現(xiàn)在說下具體需要包含的文件吧。
1)、SignalR集線器類。用于寫一個訪求調(diào)用客戶段的函數(shù)。
2)、OWIN類。用于注冊服務(wù)器的函數(shù)。
3)、前臺的頁面(包括前臺的消息框的編寫,函數(shù)的編寫)當然前臺需要一些文件。
一般VS沒有自帶SignalR類,需要我們在開始任務(wù)之前去添加這個功能。選擇VS的工具|Nuget包管理器|Nuget包管理器控制臺|Install-Package Microsoft.Aspnet.SignalR去安裝SignalR。安裝完成后,1、我們在改項目中新建一個文件夾為ChatHubs|新建一個SignalR集線器類,并寫上如下代碼:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
using Microsoft.AspNet.SignalR; namespace SignalRMvc.ChatHubs { public class ChatHub : Hub { public void SendMessage( string name, string message) { // Clients.All.hello(); Clients.All.receiveMessage(name, message); //用戶調(diào)用客戶端的函數(shù) } } } |
2、在ChatHubs文件夾下新建一個OWIN類。并寫上如下代碼:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
using Microsoft.Owin; using Owin; [assembly: OwinStartup( typeof (SignalRMvc.ChatHubs.Startup))] namespace SignalRMvc.ChatHubs { public class Startup { public void Configuration(IAppBuilder app) { app.MapSignalR(); //服務(wù)器的hub注冊 } } } |
3、在Controllers新建一個Home控制器。并寫上如下代碼:
1
2
3
4
5
6
7
8
9
10
11
12
13
|
using System.Web.Mvc; namespace SignalRMvc.Controllers { public class HomeController : Controller { // GET: Home public ActionResult ClientChat() { return View(); } } } |
4、在控制器的方法上右擊添加視圖(不使用模板,也不使用布局頁)后。并寫上如下代碼:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
|
@{ Layout = null; } <!DOCTYPE html> < html > < head > < meta http-equiv = "Content-Type" content = "text/html; charset=utf-8" /> < title ></ title > < meta charset = "utf-8" /> < link href = "~/Content/bootstrap.min.css" rel = "stylesheet" /> @* BootStarp的引入*@ < style > #message_box { height: 400px; overflow-y: scroll; } </ style > @* 呈現(xiàn)消息 *@ </ head > < body > < div class = "container" > < div class = "row" > < div class = "jumbotron" > < ul id = "message_box" ></ ul > </ div > 發(fā)送者名稱:< input id = "text_name" class = "form-control" />< br /> 消息內(nèi)容: < textarea id = "text_message" class = "form-control" rows = "3" ></ textarea > < br /> < button id = "btn_send" class = "btn btn-block btn-success" >Send</ button > </ div > </ div > < script src = "~/scripts/jquery-3.1.0.min.js" ></ script > < script src = "~/scripts/jquery.signalR-2.2.1.min.js" ></ script > @* 上述引入的兩個文件的順序不以交換,因為下面這個文件依賴于上面那個文件 *@ < script src = "~/signalr/hubs" ></ script > <!-- 本地沒有,動態(tài)生成 --> < script > $(function () { var $messageBox = $('#message_box'); var $textMessage = $('#text_message'); var $textName = $('#text_name'); //客戶端先與服務(wù)器連接起來,拿到服務(wù)器的代理操作對象 var hubConnection = $.connection.chatHub; //注冊客戶端函數(shù) hubConnection.client.receiveMessage = function (name, message) { $messageBox.append('< li >< b >' + name + '</ b > say:' + message + '</ li >') } //啟動連接到服務(wù)器 $.connection.hub.start().done(function () { $('#btn_send').bind('click', function () { //調(diào)用服務(wù)端的函數(shù) hubConnection.server.sendMessage($textName.val(), $textMessage.val()); }); }); }); </ script > </ body > </ html > |
如果直接復制使用。要注意前臺的代碼引入的文件的目錄及版本。前臺代碼的命名的首字母最好使用小寫,后臺代碼的首字母最好使用大寫。因為js默認使用的是駝峰命名法,C Sharp使用帕斯卡命名方式。如果沒有注重這個細節(jié)就會很容易出錯。因為后臺代碼在執(zhí)行的時候會動態(tài)的生成一些JS代碼,JS代碼的默認使用的駝峰命名法。如果你在前臺的代碼用了帕斯卡命名方式就很容易出錯了。并且還不好找。我是有過親身經(jīng)歷的。
下面我們在本地測試下:分別使用FireFox和Chrome來模擬兩個客戶端,當然自身的電腦也就服務(wù)端。效果圖如下:
以上就是本文的全部內(nèi)容,希望對大家的學習有所幫助,也希望大家多多支持服務(wù)器之家。