一、简介
在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); } }