一、前言
大多數系統裡面好像都有獲取消息的功能,但這些消息來源都不是實時的,比如你開兩個浏覽器,用兩個不同的賬號登錄,用一個賬號給另外一個賬號發送消息,然而並不會實時收到消息,必須要自己手動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/
本文版權歸作者和博客園共有,歡迎轉載,但未經作者同意必須保留此段聲明,且在文章頁面明顯位置給出原文連接,否則保留追究法律責任的權利。如果覺得還有幫助的話,可以點一下右下角的【推薦】,希望能夠持續的為大家帶來好的技術文章!想跟我一起進步麼?那就【關注】我吧