一、前言
大多數系統裡面好像都有獲取消息的功能,但這些消息來源都不是實時的,比如你開兩個浏覽器,用兩個不同的賬號登錄,用一個賬號給另外一個賬號發送消息,然而並不會實時收到消息,必須要自己手動F5刷新一下頁面才會顯示自己的消息,這樣感覺用戶體驗不太好。之前看了Learning hard關於Signalr的文章,剛好自己項目中有用到獲取實時消息的功能,然而我們項目中就是用js代碼setinterval方法進行1秒刷新讀取數據的,這樣嚴重給服務器端添加負擔,影響系統性能!所以自己稍微研究了一下,下面是自己的一些理解,如果有不對的地方,請大家加以斧正!
二、實現原理
下面談一下自己對Signalr的理解,Signalr可以進行遠程分布式實時通信,都是使用遠程代理來實現,其中有兩大內部對象,第一個是Persisten Connection,用於客戶端和服務器端的持久連接,第二個是Hub(集線器)對象,主要用於信息交互,將服務器端的數據推送(push)至客戶端,大致原理如下:
1、客戶端建立與服務器端的連接
2、客戶端調用服務器端的方法
3、服務器端通過客戶端發送的請求,響應數據,再將數據推送至客戶端
三、Signalr實現消息推送
具體操作實現如下:
1、創建一個應用程序,我這裡創建的是MVC應用程序
2、引用相關組件,右鍵引用》選擇管理Nuget程序包
3、搜索Signalr,如圖所示:

點擊安裝,在應用程序的Scripts文件夾裡面會自動生成兩個js文件,如圖所示:

4、添加集成器類

5、注冊signalr/hubs,在Startup.cs裡面添加如下代碼

6、新建控制器MessageController,然後在控制器裡面新建兩個視圖方法SendMessage和ReceiveMessage,為了讓效果看起來更直觀,一個頁面用於發送消息,一個頁面用於接收消息,如圖所示:

7、在我們剛剛新建的集成器類MyHub類裡面添加代碼:
(特別說明一下,這裡的InsertMsg方法主要是將客戶端發送的消息信息保存到數據庫裡面,便於消息讀取,為了快速創建數據庫表,我采用的code first方法來創建的,至於你想用什麼方式創建表,那都是可以的。)
namespace Signalr.Models
{
[HubName("MyHub")]
public class MyHub : Hub
{
MessageDbContext _db = new MessageDbContext();
public void Send(string title, string message)
{
this.InsertMsg(title, message);
// 調用所有客戶端的sendMessage方法
Clients.All.sendMessage(message);
}
private void InsertMsg(string title, string message)
{
Message msg = new Message();
msg.Title = title;
msg.MsgContent = message;
_db.Messages.Add(msg);
_db.SaveChanges();
}
}
}
表結構如圖所示:

8、控制器MessageController後台代碼
public class MessageController : Controller
{
private MessageDbContext _db = new MessageDbContext();
public ActionResult SendMessage()
{
return View();
}
public ActionResult ReceiveMessage()
{
return View();
}
[HttpPost]
public JsonResult MsgCount()
{
var count = this._db.Messages.Where(p=>p.IsRead==0).Count();
return Json(new {count=count},JsonRequestBehavior.AllowGet);
}
}
9、前端頁面代碼(SendMessage.cshtml)
@{
ViewBag.Title = "發送消息";
}
<title>發送消息</title>
<script src="~/Scripts/jquery-1.10.2.js"></script>
<script src="~/Scripts/jquery.signalR-2.2.0.min.js"></script>
<script src="~/signalr/hubs"></script>
<script type="text/javascript">
$(function () {
// 引用自動生成的集線器代理
var chat = $.connection.MyHub;
// 定義服務器端調用的客戶端sendMessage來顯示新消息
chat.client.sendMessage = function (title, message) {
// 向頁面發送接收的消息
sendMsg();
};
// 集成器連接開始
$.connection.hub.start().done(function () {
sendMsg();
// 服務連接完成,給發送按鈕注冊單擊事件
$('#sendmessage').click(function () {
// 調用服務器端集線器的Send方法
chat.server.send($("#title").val(), $('#message').val());
});
});
});
function sendMsg() {
var options = {
url: '/Message/MsgCount',
type: 'post',
success: function (data) {
$("#count").html(data.count);
}
};
$.ajax(options);
}
</script>
<h2>
發送消息
</h2>
<div>
<label>我的消息:</label>
<span id="count"></span>條
</div>
<p>
<div>
標題:
<input type="text" id="title" />
</div>
<br /><br />
<div>
內容:
<textarea id="message" rows="4" cols="30"></textarea>
</div>
<br /><br />
<div>
<input type="button" id="sendmessage" value="發送" />
</div>
</p>
10、前端頁面代碼(ReceiveMessage.cshtml)
@{
ViewBag.Title = "接受消息";
}
<title>接受消息</title>
<script src="~/Scripts/jquery-1.10.2.js"></script>
<script src="~/Scripts/jquery.signalR-2.2.0.min.js"></script>
<script src="~/signalr/hubs"></script>
<script type="text/javascript">
$(function () {
// 引用自動生成的集線器代理
var chat = $.connection.MyHub;
// 定義服務器端調用的客戶端sendMessage來顯示新消息
chat.client.sendMessage = function (title, message) {
// 向頁面發送接收的消息
MsgCount();
var html = "<div>標題:" + title + "消息內容:" + message + "</div>";
$("#msgcontent").after(html);
};
// 集成器連接開始
$.connection.hub.start().done(function () {
MsgCount();
});
});
function MsgCount() {
var options = {
url: '/Message/MsgCount',
type: 'post',
async:false,
data: { title: $("#title").val(), msgcontent: $("#sendmessage").val() },
success: function (data) {
$("#count").html(data.count);
}
};
$.ajax(options);
}
</script>
<h2>
接收消息
</h2>
<div>
<label>我的消息:</label>
<span id="count"></span>條
<br />
<br />
<div id="msgcontent"></div>
</div>
好了,大功告成,可能你有點疑問的是這個js文件引用地方在哪裡

不防我們運行頁面,按F12查看一下,它會自動在這裡生成一個js文件,我們只要在頁面中引用這個路徑即可

四、頁面效果(見證奇跡的時刻到了,哈哈哈~~~)
為了讓頁面效果更為直觀,我這裡用IE打開SendMessage.cshtml頁面,用Google打開ReceiveMessage.cshtml頁面。

權責申明
作者:SportSky 出處: http://www.cnblogs.com/sportsky/
本文版權歸作者和博客園共有,歡迎轉載,但未經作者同意必須保留此段聲明,且在文章頁面明顯位置給出原文連接,否則保留追究法律責任的權利。如果覺得還有幫助的話,可以點一下右下角的【推薦】,希望能夠持續的為大家帶來好的技術文章!想跟我一起進步麼?那就【關注】我吧