長輪詢:客戶端向服務器發送Ajax請求,服務器接到請求后hold住連接,直到有新消息才返回響應信息並關閉連接,客戶端處理完響應信息后再向服務器發送新的請求。
優點:在無消息的情況下不會頻繁的請求。
缺點:服務器hold連接會消耗資源。
if not exists(select 1 from sys.databases where name='beidoudemo') begin Create Database beidoudemo end go use beidoudemo go if exists(select 1 from sysobjects where name='AjaxPolling' and type='u') begin drop table AjaxPolling end go Create table AjaxPolling ( id int identity Primary key, userName varchar(30) not null, passwordKey varchar(50) not null )
選用Jquery中的AJAX方法發送異步請求
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="LongPolling.aspx.cs" Inherits="AjaxFinder.LongPolling" %>
<!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">
<script src="Scripts/jquery-1.4.1.js" type="text/javascript"></script>
<title></title>
<script type="text/javascript">
var userID = 0;
function SendXHR() {
$.ajax({
type: "post", //AJAX請求類型
url: "LongPollingServer.ashx", //請求url
cache: false, //無緩存
timeout: 1000 * 80, //AJAX請求超時時間為60秒
data: { time: 60, userID: userID }, //參數time時間為最多等待(后台保持)時間(60秒無論是否有數據立即返回),單位為秒。userID判斷詩句是否為新數據的標識
success: function (data, textStatus) {
var obj = document.getElementById("NameDisplay");
//判斷返回成功還是失敗 如果后台保持連接的時間一到並且沒有新數據就會返回fail開頭失敗的數據
if (data != null && data != "" && !(data.indexOf("fail") != -1)) {
var strarr = data.split(",");
// alert(strarr[0]);
userID = strarr[0];
obj.innerHTML = "親!有新用戶注冊哦!用戶名:" + strarr[1];
}
else {
obj.innerHTML = "親!暫無新用戶注冊哦";
}
SendXHR();//請求后立即發起AJAX請求
},
error: function (XMLHttpRequest, textStatus, errorThrown) {
//New Error do something
if (textStatus == "timeout") {
//超時間
SendXHR();
}
}
});
}
window.onload = function () {
SendXHR();
}
</script>
</head>
<body>
<form id="form1" runat="server">
<div>
</div>
<div id="NameDisplay">
</div>
</form>
</body>
</html>
后台代碼實現
using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Text; using System.Net; using System.Threading; using System.Data; namespace AjaxFinder { /// <summary> /// AJAX長輪詢后台處理頁面 /// 主要用於保持連接 /// 有數據返回,無數據繼續保持連接超時返回 /// 請不要關注代碼編寫規范等一些問題。這僅僅是一個DEMO /// 還存在諸多問題 /// </summary> public class LongPollingServer : IHttpHandler { public void ProcessRequest(HttpContext context) { /* context.Response.ContentType = "text/plain"; */ int SendTime = 0; //最多等待時間 int userID = 0; //上一次的用戶ID if (context.Request.Form["time"] != null&&context.Request.Form["time"].ToString()!="") { SendTime =int.Parse(context.Request.Form["time"].ToString());//接收傳來的的后台要保持時間 } if (context.Request.Form["userID"] != null && context.Request.Form["userID"].ToString() != "") { userID = int.Parse(context.Request.Form["userID"].ToString()); } int i = 0;//計算超時時間(秒) while (true) { Thread.Sleep(1000);//停留一千毫秒(1秒) i++; if (i < SendTime) { if (NameStr(userID) != "") { context.Response.Write(NameStr(userID)); break; } } if (i == SendTime) { context.Response.Write("fail:無數據"); break; } } } /// <summary> /// 獲得用戶名 /// </summary> /// <param name="userID"></param> /// <returns></returns> private string NameStr(int userID) { string result = string.Empty; string Sqlstr = "select top 1 ID,UserName from AjaxPolling Order by ID desc"; DataSet ds = new DataSet(); ds = SQLHelper.Query(Sqlstr, null); if (ds != null) { if (ds.Tables[0].Rows.Count >= 1) { if (int.Parse(ds.Tables[0].Rows[0][0].ToString()) != userID || 0 ==int.Parse(ds.Tables[0].Rows[0][0].ToString())) { result = ds.Tables[0].Rows[0][0].ToString() + "," + ds.Tables[0].Rows[0][1].ToString(); } } } return result; } public bool IsReusable { get { return false; } } } }
