寫在前面的廢話
在寫關於SignalR的學習筆記之前研究了幾天的webSocket,畢竟這才是未來的技術趨勢,雖然很早就聽說過WebSocket,但是並沒有在實際項目中遇到過,所以也就沒有深入研究。通過這幾天的研究發現WebSocket雖好,但是實現起來還是蠻繁瑣的(有第3方封裝好的庫可以直接調用),特別是對於握手成功之后數據幀的解析,這需要對RFC6455非常了解。而且IE10以下的瀏覽器並不支持,而且服務端也得IIS8及以上才支持。
通過百度各位大牛的足跡,了解到了SignalR,這貨是微軟封裝好的基於B/S架構下的即時通訊組件,說白了就是如果條件支持,它就使用WebSocket技術來進行瀏覽器與服務器的實時通信,如果使用者的環境不支持的話,它就會采取Ajax輪循的方法來達到這一目的。而且還不用你解析WebSocket的數據幀,同時又能兼顧那些舍不得升級系統的老忠戶,這不是一舉兩得么?
不過說真的,做為技術人員,學習最原始的WebSocket,並自己寫代碼去實現握手及解析數據幀,那是非常棒的一件事,只能說是有百利而無一害,不過這都是后話了。
關於這篇文章
首先聲明這篇文章不是我的原創(有那心,沒那能力哎!),充其量只是個學習筆記,如果有興趣的話,請參考原文:Getting Started with SignalR 2,好了不說廢話了,咱們就來講一下如何利用SignalR來實現一個即時聊天的頁面,聊天界面如下圖所示。
創建項目
我使用的是Visual Studio 2015,下面的步驟也是基於vs2015來的,其它版本應該類似。
1.使用vs創建一個新的ASP.NET Web Application
2.在選擇新建項目對話框中,選擇Empty模板,然后點擊OK創建項目
3.在Solution Explorer,右擊該項目,選擇Add--New Item,然后選擇Visual C#--Web--SignalR菜單,接着選中SignalR Hub Class(v2)選項,然后輸入文件名ChatHub.cs后,創建文件。
注意:可以使用NuGet命令 ```
install-package Microsoft.AspNet.SignalR

4.然后在**ChatHub**類中輸入下面這段代碼。
using Microsoft.AspNet.SignalR;
namespace SignalRChat
{
public class ChatHub : Hub
{
public void Send(string name, string message)
{
// 客戶端通過調用broadcastMessage來獲取數據
Clients.All.broadcastMessage(name, message);
}
}
}
5.在**Solution Explorer**中,右擊項目,然后添加一個名為**Startup**的類,然后輸入下面這段代碼。
using Microsoft.Owin;
using Owin;
[assembly: OwinStartup(typeof(SignalRChat.Startup))]
namespace SignalRChat
{
public class Startup
{
public void Configuration(IAppBuilder app)
{
app.MapSignalR();
}
}
}
6.在項目中添加一個靜態網頁文件,並命名為**index.html**,然后右擊該網頁文件,並選擇**Set As Start Page**
7.在**Index.html**中輸入下面的代碼,注意引用正確的文件名。
<!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>
<!--Reference the jQuery library. -->
<script src="Scripts/jquery-1.10.2.js"></script>
<!--Reference the SignalR library. -->
<script src="Scripts/jquery.signalR-2.1.2.js"></script>
<!--Reference the autogenerated SignalR hub script. -->
<script src="signalr/hubs"></script>
<!--Add script to update the page and send messages.-->
<script type="text/javascript">
$(function () {
// Declare a proxy to reference the hub.
var chat = $.connection.chatHub;
// Create a function that the hub can call to broadcast messages.
chat.client.broadcastMessage = function (name, message) {
// Html encode display name and message.
var encodedName = $('<div />').text(name).html();
var encodedMsg = $('<div />').text(message).html();
// Add the message to the page.
$('#discussion').append('<li><strong>' + encodedName
+ '</strong>: ' + encodedMsg + '</li>');
};
// Get the user name and store it to prepend to messages.
$('#displayname').val(prompt('Enter your name:', ''));
// Set initial focus to message input box.
$('#message').focus();
// Start the connection.
$.connection.hub.start().done(function () {
$('#sendmessage').click(function () {
// Call the Send method on the hub.
chat.server.send($('#displayname').val(), $('#message').val());
// Clear text box and reset focus for next comment.
$('#message').val('').focus();
});
});
});
</script>
</body>
</html>
8.保存項目,並按F5運行
## 運行結果
項目運行起來后,同時用多個瀏覽器打開的,輸入各自的姓名之后,就能夠實現即時通訊了。回到我們的vs,還能夠看到自動生成的hubs腳本文件,如下圖所示。

## 其它想說的話
使用SignalR,很容易就可以實現B/S模式下的即時通訊。
### 服務端
在**ChatHub**類中,可以看到它繼承自**Microsoft.AspNet.SignalR.Hub**。在這個類(**ChatHub**)中定義的公共方法可以被網頁內的腳本訪問(服務器端的方法名和類名都會被默認設置為首字母小寫的方式,想要自定義名稱的話,可以參考**HubName**和**HubMethodName**這兩個類)
在這段代碼中(**ChatHub**類),客戶端通過調用**ChatHub.Send**方法,並把名稱和消息內容做為參數傳遞給**ChatHub**。而**ChatHub**則通過**Clients.All.broadcastMessage**方法把該消息廣播給所有客戶端。
### 客戶端
客戶端通過**jquery.signalR.js**和**signalr/hubs**來與服務器進行通信,首先它要聲明一個代理。
var chat = $.connection.chatHub
然后它要再聲明一個回調函數,這個回調函數主要是為了讓服務器進行調用,從而將數據推送到客戶端。
chat.client.broadcastMessage = function (name, message) {
//TODO:接收服務器推送的消息
};
而下面的代碼則是為了確保在將消息發送到服務器之前已經與服務器建立了連接。
// 與服務器建立連接后才能發送消息到服務器
$.connection.hub.start().done(function () {
$('#sendmessage').click(function () {
// 調用服務器端的ChatHub.Send方法,並把消息發送到服務器
chat.server.send("name", "message");
});
});