服务端:
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="进入" οnclick="comin()" /><br />
<input type="text" id="message" /><input type="button" value="发送" οnclick="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>
以上代码均测试通过。