服务端:
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>
配置文件:
web.Config
<httpHandlers> <add verb="*" path="MyHandler.ashx" type="WebApplication2.MyHandler"/> <add verb="*" path="MyAsyncHandler.ashx" type="WebApplication2.MyAsyncHandler"/> </httpHandlers>
以上代码均测试通过。