ASP.NET MVC 实现基于 XMLHttpRequest long polling 的 Comet

作者:袖梨 2022-06-25


我个人的理解是,看起来就像在Web环境中客户端能订阅服务端的事件,服务器端通过事件去通知客户端。如果服务器端用 ASP.NET 来实现,可以利用 .NET 的事件驱动机制,很有意思,下面的示例代码将展示这一点。

先看Web前端js代码:

 代码如下 复制代码

jQuery(function ($) {
    function long_polling() {
        $.getJSON('/comet/LongPolling', function (data) {
            if (data.d) {
                $('#logs').append(data.d + "
");
            }
            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。

相关文章

精彩推荐