用 ASP.NET MVC 实现基于 XMLHttpRequest long polling(长轮询) 的 Comet
之前在“反向Ajax,第1部分:Comet介绍”(英文版)文章中学习了“基于 Multipart XMLHttpRequest 的 Comet”的知识,然后用 ASP.NET MVC 实现了一个,详见用 ASP.NET MVC 实现基于 Multipart XMLHttpRequest 的 Comet。
今天继续学习了基于 XMLHttpRequest long polling 的 Comet,又用 ASP.NET MVC 实现了一个,在这篇文章中分享一下。
先了解一下什么是XMLHttpRequest long polling?
这是一种推荐的实现Comet的做法,打开一个到服务器端的Ajax请求然后等待响应。服务器端需要一些特定的功能来允许请求被挂起,只要一有事件发生,服务器端就会在挂起的请求中送回响应并关闭该请求。然后客户端就会使用这一响应并打开一个新的到服务器端的长生存期的Ajax请求。
This is a recommended method to implement Comet is to open an Ajax request to the server and wait for the response. The server requires specific features on the server side to allow the request to be suspended. As soon as an event occurs, the server sends back the response in the suspended request and closes it. The client then consumes the response and opens a new long-lived Ajax request to the server.
我个人的理解是,看起来就像在Web环境中客户端能订阅服务端的事件,服务器端通过事件去通知客户端。如果服务器端用 ASP.NET 来实现,可以利用 .NET 的事件驱动机制,很有意思,下面的示例代码将展示这一点。
先看Web前端js代码:
jQuery(function ($) {
function long_polling() {
$.getJSON('/comet/LongPolling', function (data) {
if (data.d) {
$('#logs').append(data.d + "<br/>");
}
long_polling();
});
}
long_polling();
});
js代码很简单,就是一个递归调用(调用在callback时进行的),通过jQuery的$.getJSON发起Ajax请求,'/comet/LongPolling' 表示请求的服务端 CometController 的 LongPolling Action 的网址。这里我们可以看出实现 Comet 的难点不在 Web 前端,而是在服务器端。
接下来重点看 Web 服务器 ASP.NET MVC Controller 的代码。
首先要注意的是为了响应 XMLHttpRequest long polling 请求,我们需要实现一个异步控制器(AsyncController),如果您对 AsyncController 不熟悉,建议阅读MSDN上的文章 Using an Asynchronous Controller in ASP.NET MVC 。
先上 Controller 的实现代码:
(注:该控制器实现的功能是每隔5秒钟向客户端发送服务器当时间)
public class CometController : AsyncController
{
//LongPolling Action 1 - 处理客户端发起的请求
public void LongPollingAsync()
{
//计时器,5秒种触发一次Elapsed事件
System.Timers.Timer timer = new System.Timers.Timer(5000);
//告诉ASP.NET接下来将进行一个异步操作
AsyncManager.OutstandingOperations.Increment();
//订阅计时器的Elapsed事件
timer.Elapsed += (sender, e) =>
{
//保存将要传递给LongPollingCompleted的参数
AsyncManager.Parameters["now"] = e.SignalTime;
//告诉ASP.NET异步操作已完成,进行LongPollingCompleted方法的调用
AsyncManager.OutstandingOperations.Decrement();
};
//启动计时器
timer.Start();
}
//LongPolling Action 2 - 异步处理完成,向客户端发送响应
public ActionResult LongPollingCompleted(DateTime now)
{
return Json(new { d = now.ToString("MM-dd HH:mm:ss ") +
"-- Welcome to cnblogs.com!" },
JsonRequestBehavior.AllowGet);
}
}
实现异步控制器需要继承 System.Web.Mvc.AsyncController,并将 Action 分解为两个,比如 Action 叫 LongPolling,则分解为 LongPollingAsync 与 LongPollingCompleted 。LongPollingAsync 接受客户端请求,并发起异步操作;异步操作完成,调用LongPollingCompleted。
AsyncManager.OutstandingOperations.Increment(); 告诉ASP.NET接下来将进行一个异步操作。
AsyncManager.OutstandingOperations.Decrement(); 告诉ASP.NET异步操作完成,请调用LongPollingCompleted()方法。
示例代码中的异步操作就是将服务器当前时间作为参数传递给 LongPollingCompleted() 方法,LongPollingCompleted() 获取服务器当前时间并传递给客户端,客户端收到后将之显示出来,将继续发起 Ajax 请求 ... 这样周而复始,实现了基于 XMLHttpRequest long polling 的 Comet。
示例代码运行结果如下:
小结
以前觉得 Comet 是很高深的东西,自己动手做了之后,发觉原来没那么难。所以,重要的是动手去做!
如果不能在实际项目中去做,那就写一篇博客吧!
代码下载
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 一个奇形怪状的面试题:Bean中的CHM要不要加volatile?
· [.NET]调用本地 Deepseek 模型
· 一个费力不讨好的项目,让我损失了近一半的绩效!
· .NET Core 托管堆内存泄露/CPU异常的常见思路
· PostgreSQL 和 SQL Server 在统计信息维护中的关键差异
· DeepSeek “源神”启动!「GitHub 热点速览」
· 我与微信审核的“相爱相杀”看个人小程序副业
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· C# 集成 DeepSeek 模型实现 AI 私有化(本地部署与 API 调用教程)
· spring官宣接入deepseek,真的太香了~
2009-10-17 SQL Server 2005中NTEXT与NVARCHAR(MAX)
2008-10-17 按效果付费
2005-10-17 网站分类调整