Comet:Jquery+asp.net實現http長連接(LongPoll)


<%@ Page Language="C#" AutoEventWireup="true" CodeFile="JqueryAjaxLongPoll.aspx.cs" Inherits="JqueryAjaxLongPoll" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
    <title>無標題頁</title>
    <script type="text/javascript" src="script/jquery-1.2.6.js"></script>
    <script type="text/javascript">
        $(document).ready(function(){
            $("#Button1").bind("click",{btn:$("#Button1")},function(evdata){
                $.ajax({
                    type:"POST",
                    url:"JqueryAjaxLongPoll.aspx",
                    dataType:"json",
                    timeout:10000,
                    data:{ajax:"1",time:"10000"},
                    success:function(data,textStatus){
                            //alert("ok!");
                            evdata.data.btn.click();
                    },
                    complete:function(XMLHttpRequest,textStatus){
                            if(XMLHttpRequest.readyState=="4"){
                                alert(XMLHttpRequest.responseText);
                            }
                    },
                    error: function(XMLHttpRequest,textStatus,errorThrown){
                            //$("#ajaxMessage").text($(this).text()+" out!")
                            alert("error:"+textStatus);
                            if(textStatus=="timeout")
                                evdata.data.btn.click();
                    }
                });
            });

            /*$("#ajaxMessage").ajaxStart(function(){
                $(this).text("准備建立請求.readyState0:");
            });
            $("#ajaxMessage").ajaxSend(function(evt, request, settings){
                $(this).text("開始請求,准備發送數據.readyState1:"+request.readyState);
            });
            $("#ajaxMessage").ajaxComplete(function(event,request, settings){
                if(request.status==200)
                    $(this).text("請求完成.readyState4:"+request.readyState);
            });
            $("#ajaxMessage").ajaxStop(function(){
                $(this).text("請求結束.");
            });*/
        });
    </script>
</head>
<body>
    <form id="form1" runat="server">
    <div>
        <input id="Button1" type="button" value="AjaxLongPoll" />
        <label id="ajaxMessage"></label>
    </div>
    </form>
</body>
</html>
using System;
using System.Data;
using System.Configuration;
using System.Collections;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using System.Threading;

public partial class JqueryAjaxLongPoll : System.Web.UI.Page
{
    protected void Page_Load(object sender, EventArgs e)
    {
        if (Request.Form["ajax"] == "1")
        {
            //Response.End();
            int time = Convert.ToInt32(Request.Form["time"]);
            DateTime date1 = DateTime.Now.AddMilliseconds((double)time);
            bool ready = false;
            while (Response.IsClientConnected)
            {
                Thread.Sleep(3000);
                if (DateTime.Compare(date1, DateTime.Now) < 0)
                {
                    Response.End();
                    break;
                }
                //ready = true;
                if (ready)
                {
                    Response.Write("SetValue('" + DateTime.Now.ToString() + "')");
                    //Response.Flush();
                    Response.End();
                    break;
                }
                else
                {

                }
            }
        }
        else
        {
            if (!Page.IsPostBack)
            {

            }
        }
    }
}

對代碼的說明:利用jquery,很方便的就能實現ajax,上面設置了ajax的timeout時間,由於設置了timeout將會造成不能保持長連接,到了時間ajax自動會報“超時”的錯誤,也就是會調用error方法,此時textStatus=="timeout",timeout后重新進行ajax請求。服務器接受ajax請求的時候,會接收一個超時時間的值,超時的情況下服務器端的處理也立即停止。當客戶端成功獲取返回結果時,也會立即進行新的ajax請求,如此循環。

為什么要設置客戶端的ajax超時值呢?因為服務器為了保持請求(阻塞請求),必須有一個無限循環,循環的結束條件就是獲取到了返回結果,如果客戶端關閉了(客戶端瀏覽器的關閉不會發消息給服務器),服務器無法知道客戶端已經關了,這個請求沒必要處理下去了。最終會造成資源過度浪費,只要用一個折中的辦法,限制超時時間。

可以不必設置客戶端ajax的超時時間,但進行請求的時候傳遞一個超時值給服務器,服務器在處理的時候,如果超時時間到了的話,還沒有客戶端需要的結果,這時傳遞一個超時信息給客戶端,客戶端接收到了此信息,根據情況重新進行ajax請求。XMLHttpRequest沒有超時的參數,Jquery用window.setTimeout自己封裝的(到了定時時間運行超時處理方法,和XMLHttpRequest結束方法)。可以根據這個思路來改變一下,IBM上介紹的LONG POLL好像也是這樣的。

$(document).ready(function(){
            $("#Button1").bind("click",{btn:$("#Button1")},function(evdata){
                $.ajax({
                    type:"POST",
                    url:"JqueryAjaxLongPoll.aspx",
                    dataType:"json",
                    data:{ajax:"1",time:"6000000"},
                    success:function(data,textStatus){
                            //成功
                            if(data.success=="1"){
                                //客戶端處理
                                //...
                                ///重新請求
                                evdata.data.btn.click();
                            }
                            //超時
                            if(data.success=="0"){
                                evdata.data.btn.click();
                            }
                    },
                    complete:function(XMLHttpRequest,textStatus){
                            if(XMLHttpRequest.readyState=="4"){
                                alert(XMLHttpRequest.responseText);
                            }
                    },
                    error: function(XMLHttpRequest,textStatus,errorThrown){
                            //$("#ajaxMessage").text($(this).text()+" out!")
//                            alert("error:"+textStatus);
//                            if(textStatus=="timeout")
                                evdata.data.btn.click();
                    }
                });
            });

后台代碼變更后:

if (Request.Form["ajax"] == "1")
        {
            int time = Convert.ToInt32(Request.Form["time"]);
            DateTime date1 = DateTime.Now.AddMilliseconds((double)time);
            bool ready = false;
            while (Response.IsClientConnected)
            {
                Thread.Sleep(3000);
                if (DateTime.Compare(date1, DateTime.Now) < 0)
                {
                    Response.Write("{success:'0'}");
                    Response.End();
                    break;
                }
                //此處進行請求處理,有結果了置ready = true
                //ready = true;
                if (ready)
                {
                    Response.Write("{success:'1'}");
                    Response.End();
                    break;
                }
            }
        }
        else
        {
            if (!Page.IsPostBack)
            {

            }
        }

上面的方法應該就可以滿足要求了,具體的超時時間可以根據情況來設置。這也是我根據IBM上介紹的“server push”思路,來實現了其中的一種,也不知道有沒有問題,還請大家多多賜教。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM