一、簡介
在Asp.net MVC實現的Comet推送的原理很簡單。
服務器端:接收到服務器發送的AJAX請求,服務器端並不返回,而是將其Hold住,待到有東西要通知客戶端時,才將這個請求返回。
客戶端:請求異步Action,當接收到一個返回時,立即又再發送一個。
缺點:會長期占用一個Asp.net處理線程。但相比於輪詢,其節省了帶寬。
示例:
新建一個Controller如下:
//Comet服務器推送控制器(需設置NoAsyncTimeout,防止長時間請求掛起超時錯誤) [NoAsyncTimeout, SessionState(SessionStateBehavior.ReadOnly)] public class CometController : AsyncController //需要繼承自異步的AsyncController { /// <summary> /// 異步方法,處理客戶端發起的請求 /// </summary> public void IndexAsync() { AsyncManager.OutstandingOperations.Increment(); AsyncManager.Parameters["info"] = "怎么了"; AsyncManager.OutstandingOperations.Decrement(); } /// <summary> /// 當異步線程完成時向客戶端發送響應 /// </summary> /// <param name="token">數據封裝對象</param> /// <returns></returns> public ActionResult IndexCompleted(string info) { return Json(info, JsonRequestBehavior.AllowGet); } }
隨便找一個頁面,通過AJAX請求這一個異步Action:
<html> <head> <title>AJAX測試</title> <script src="/Content/jquery-1.10.2.min.js"></script> <script type="text/javascript"> $(function () { getCometServerPush(); }) function getCometServerPush() { $.ajax({ cache: false, url: '/Comet/Index', success: function (data) { $("#info").html(data); getCometServerPush(); } }); } </script> </head> <body> <div id="info"></div> </body> </html>
上面的示例,如果你在Action上下一個斷點,會不停的看到斷點在循環。說明異步客戶端不停地在推送。當然這個示例僅僅是說明推送的原理。
二、應用
應用:監控服務器上的一個txt文件,當有變化時,推送內容到客戶端。
//Comet服務器推送控制器(需設置NoAsyncTimeout,防止長時間請求掛起超時錯誤) [NoAsyncTimeout, SessionState(SessionStateBehavior.ReadOnly)] public class CometController : AsyncController //需要繼承自異步的AsyncController { /// <summary> /// 異步方法,處理客戶端發起的請求 /// </summary> public void IndexAsync() { AsyncManager.OutstandingOperations.Increment(); FileSystemWatcher FSW = new FileSystemWatcher(); FSW.Filter = "123.txt"; //僅僅監控123.txt文件 FSW.Path = Server.MapPath(@"/"); //設置監控路徑 FSW.EnableRaisingEvents = true; //啟動監控 //FileSystemWatcher暫時有個多次觸發的問題,但與本推送示例無關,故不解決 FSW.Changed += (object source, FileSystemEventArgs e) => { AsyncManager.Parameters["info"] = System.IO.File.ReadAllText(Server.MapPath(@"/123.txt"),System.Text.Encoding.Default); ; AsyncManager.OutstandingOperations.Decrement(); }; } /// <summary> /// 當異步線程完成時向客戶端發送響應 /// </summary> /// <param name="token">數據封裝對象</param> /// <returns></returns> public ActionResult IndexCompleted(string info) { return Json(info, JsonRequestBehavior.AllowGet); } }
更多流逼的功能,留着讀者自由發揮。
