服務端:
using System; using System.Collections.Generic; using System.Linq; using System.Threading; using System.Web; namespace WebApplication2 { public class MyHandler : IHttpHandler { /// <summary> /// 消息下發請求 /// </summary> /// <param name="context"></param> public void ProcessRequest(HttpContext context) { //不讓客戶端緩存 context.Response.Cache.SetCacheability(HttpCacheability.NoCache); List<MyAsyncResult> userlist = MyAsyncHandler.Queue; //唯一標識 string sessionId = context.Request.QueryString["sessionId"]; //消息內容 string message = context.Request.QueryString["message"] + " " + userlist.Count.ToString(); List<string> error = new List<string>(); foreach (MyAsyncResult res in userlist) { //如果不是自己就推送信息 if (res.SessionId != sessionId) { res.Message = message; try { //推送內容 res.SetCompleted(true); } catch (Exception) { //如果推送失敗(客戶端已斷開,網絡異常等) //則刪除該標志 error.Add(res.SessionId); } } } foreach (var v in error) { userlist.RemoveAll(fun => fun.SessionId == v); } } public bool IsReusable { get { return true; } } } public class MyAsyncHandler : IHttpAsyncHandler { public static List<MyAsyncResult> Queue = new List<MyAsyncResult>(); public void ProcessRequest(HttpContext context) { } public bool IsReusable { get { return true; } } public IAsyncResult BeginProcessRequest(HttpContext context, AsyncCallback cb, object extraData) { //接到連接請求 //不讓客戶端緩存 context.Response.Cache.SetCacheability(HttpCacheability.NoCache); //獲取唯一標識 string sessionId = context.Request.QueryString["sessionId"]; if (Queue.Count(fun => fun.SessionId == sessionId) > 0) { int index = Queue.IndexOf(Queue.Find(fun => fun.SessionId == sessionId)); Queue[index].Context = context; Queue[index].CallBack = cb; return Queue[index]; } //如果不存在則加入隊列 MyAsyncResult asyncResult = new MyAsyncResult(context, cb, sessionId); Queue.Add(asyncResult); return asyncResult; } public void EndProcessRequest(IAsyncResult result) { //長連接結束前寫入內容 MyAsyncResult rslt = (MyAsyncResult)result; //拼裝返回內容 rslt.Context.Response.Write(rslt.Message); rslt.Message = string.Empty; } } public class MyAsyncResult : IAsyncResult { /// <summary> /// 是否結束請求 /// true:完成 /// false:阻塞 /// </summary> public bool IsCompleted { get; private set; } public WaitHandle AsyncWaitHandle { get; private set; } public object AsyncState { get; private set; } public bool CompletedSynchronously { get { return false; } } public HttpContext Context { get; set; } public AsyncCallback CallBack { get; set; } /// <summary> /// 自定義標識 /// </summary> public string SessionId { get; set; } /// <summary> /// 自定義消息 /// </summary> public string Message { get; set; } public MyAsyncResult(HttpContext context, AsyncCallback cb, string sessionId) { this.SessionId = sessionId; this.Context = context; this.CallBack = cb; IsCompleted = true; } /// <summary> /// 發送消息 /// </summary> /// <param name="iscompleted">確認下發信息</param> public void SetCompleted(bool iscompleted) { if (iscompleted && this.CallBack != null) { CallBack(this); } } } }
客戶端:
<!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> <title></title> </head> <body> <input type="text" id="sessionId" /><input type="button" value="進入" onclick="comin()" /><br /> <input type="text" id="message" /><input type="button" value="發送" onclick="send()" /> <div id="messages"> </div> <script type="text/javascript"> function comin() { var xmlHttp = ajaxFunction(); var url = "MyAsyncHandler.ashx?sessionId=" + document.getElementById("sessionId").value; xmlHttp.onreadystatechange = function () { if (xmlHttp.readyState == 4) { if (xmlHttp.status == 200) { document.getElementById("messages").innerHTML += xmlHttp.responseText + "<br>"; //連接已經結束,馬上開啟另外一個連接 comin(); } } } xmlHttp.open("get", url, true); xmlHttp.send(null); } function send() { var xmlHttp = ajaxFunction(); var url = "MyHandler.ashx?sessionId=" + document.getElementById("sessionId").value + "&message=" + document.getElementById("message").value; xmlHttp.onreadystatechange = function () { if (xmlHttp.readyState == 4) { if (xmlHttp.status == 200) { } else { alert("錯誤:" + xmlHttp.status); } } } xmlHttp.open("get", url, true); xmlHttp.send(null); } function ajaxFunction() { var xmlHttp; try { xmlHttp = new XMLHttpRequest(); } catch (e) { try { xmlHttp = new ActiveXObject("Msxml2.XMLHTTP"); } catch (e) { try { xmlHttp = new ActiveXObject("Microsoft.XMLHTTP"); } catch (e) { alert("您的瀏覽器不支持AJAX!"); return false; } } } return xmlHttp; } </script> </body> </html>
配置文件:

<httpHandlers> <add verb="*" path="MyHandler.ashx" type="WebApplication2.MyHandler"/> <add verb="*" path="MyAsyncHandler.ashx" type="WebApplication2.MyAsyncHandler"/> </httpHandlers>
以上代碼均測試通過。