您的位置:首页 > 理论基础 > 计算机网络

asp.net web 通过IHttpAsyncHandler接口进行消息推送

2017-06-10 13:45 344 查看
1.消息类,可直接通过这个类推送消息 HttpMessages
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Web;
namespace Holworth.Utility
{
public class HttpMessages
{
//记录所有请求的客户端
List<WebAsynResult> clients = new List<WebAsynResult>();

#region 实现该类的单例
private static readonly HttpMessages _Instance = new HttpMessages();
private HttpMessages()
{
}
public static HttpMessages Instance()
{
return _Instance;
}
#endregion

public void AddMessage(string content, WebAsynResult asyncResult)
{
//当传入的内容为"-1"时,表示为建立连接请求,即为了维持一个从客户端到服务器的连接而建立的连接
//此时将该连接保存到 List<myAsynResult> clients中,待再有消息发送过来时,该连接将会被遍历,并且会将该连接输出内容后,结束该连接
if (content == "-1")
{
clients.Add(asyncResult);
}
else
{
//将当前请求的内容输出到客户端
asyncResult.Content = content;
asyncResult.Send(null);

//否则将遍历所有已缓存的client,并将当前内容输出到客户端
foreach (WebAsynResult result in clients)
{
result.Content = content;
result.Send(null);
}

//清空所有缓存
clients.Clear();
}
}
}
}
2.异步请求接口WebAsnyHandler实现类
using System;
using System.Collections.Generic;
using System.Web;
using System.Threading;

namespace Holworth.Utility
{
/// <summary>
/// Summary description for AsnyHandler
/// </summary>
public class WebAsnyHandler : IHttpAsyncHandler
{
public WebAsnyHandler()
{
}

public IAsyncResult BeginProcessRequest(HttpContext context, AsyncCallback cb, object extraData)
{
//myAsynResult为实现了IAsyncResult接口的类,当不调用cb的回调函数时,该请求不会返回到给客户端,会一直处于连接状态
WebAsynResult asyncResult = new WebAsynResult(context, cb, extraData);
String content = context.Request.Params["content"];

//向Message类中添加该消息
HttpMessages.Instance().AddMessage(content, asyncResult);
return asyncResult;
}

#region 不必理会

public void EndProcessRequest(IAsyncResult result)
{

}

public bool IsReusable
{
get { return false; ; }
}

public void ProcessRequest(HttpContext context)
{
}
#endregion
}

}
3.异步请求结果类WebAsynResult
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Web;

namespace Holworth.Utility
{
public class WebAsynResult : IAsyncResult
{
bool _IsCompleted = false;
private HttpContext context;
private AsyncCallback cb;
private object extraData;
public WebAsynResult(HttpContext context, AsyncCallback cb, object extraData)
{
this.context = context;
this.cb = cb;
this.extraData = extraData;
}
private string _content;
public string Content
{
get { return _content; }
set { _content = value; }
}

#region IAsyncResult接口
public object AsyncState
{
get { return null; }
}

public System.Threading.WaitHandle AsyncWaitHandle
{
get { return null; }
}

public bool CompletedSynchronously
{
get { return false; }
}
public bool IsCompleted
{
get { return _IsCompleted; }
}
#endregion

//在Message类中的添加消息方法中,调用该方法,将消息输入到客户端,从而实现广播的功能
public void Send(object data)
{

context.Response.Write(this.Content);
if (cb != null)
{
cb(this);
}
_IsCompleted = true; ;
}
}
}
4.客户端 请求分两步 发送数据send和等待数据的请求,若有数据则响应继续进入等待数据的状态,若无数据进入等待状态,异步接口缓存客户端的异步请求结果
js部分
/// <reference path="jquery-1.3.2.min.js" >
function send(content) {
// alert("step=" + $("#content").val());
//var content = getUrlParam("step");
//向comet_broadcast.asyn发送请求,消息体为文本框content中的内容,请求接收类为WebAsnyHandler
$.post("comet_broadcast.asyn", { content: content });

//清空内容
$("#content").val("");
}
function getUrlParam(pName, win) {
var sUrl;
if (typeof (win) == 'string') {
sUrl = win;
if (sUrl.indexOf('?') < 0) sUrl = '?' + sUrl;
} else {
if (!win) win = window;
sUrl = win.location.search;
}
var iQ = sUrl.indexOf('?') + 1;
if (iQ > 0) {
sUrl = '&' + sUrl.substring(iQ, sUrl.length);

iQ = sUrl.indexOf('?'); //url参数中还存在url?
var key = '&' + pName + '=';
var i = sUrl.indexOf(key);
if (i > -1) {
var j = sUrl.indexOf('&', i + 1); //&Key=Val&Key2=...
if (j < 0 || (iQ > 1 && j > iQ)) j = sUrl.length;
return unescape(sUrl.substring(i + key.length, j));
}
}
return null;
};

//未找到服务响应的客户端进入等待状态,待服务端响应之后,再次等待,一直循环
function wait() {
// alert("初始化前")
$.post("comet_broadcast.asyn", { content: "-1" },
function (data, status) {
var result = $("#divResult");
result.html(result.html() + "<br/>" + data);
// alert("初始化后")
//服务器返回消息,再次立连接
wait();
}, "html"
);
}

$(function () {
//初始化连接
wait();

//测试代码
$("#btnSend").click(function () { send($("#content").val()); });
$("#content").keypress(function (event) {
if (event.keyCode === 13) {
send($("#content").val());
}
});
});

5。这里在另一个页面进行数据的推送,不过是service还是页面都可以
LongConnectServer.aspx,前台部分无关紧要,直接看后台调用
using Holworth.Utility;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;

namespace Comet_by_ASP.NET
{
public partial class LongConnectServer : System.Web.UI.Page
{
public void aa()
{
for (int i = 0; i < 1000; i++)
{

}
}
public void bb()
{
WebAsynResult asyncResult = new WebAsynResult(HttpContext.Current, null,null);
HttpMessages.Instance().AddMessage("1", asyncResult);
Thread.Sleep(1000);
HttpMessages.Instance().AddMessage("2", asyncResult);
Thread.Sleep(1000);
HttpMessages.Instance().AddMessage("3", asyncResult);
Thread.Sleep(1000);
HttpMessages.Instance().AddMessage("4", asyncResult);
Thread.Sleep(1000);
HttpMessages.Instance().AddMessage("5", asyncResult);
Thread.Sleep(1000);
HttpMessages.Instance().AddMessage("6", asyncResult);
//WebRequestUtility req = new WebRequestUtility();
//var para = new Dictionary<string, string>();
//para.Add("_method", "compute");
//para.Add("step", "1");

//req.HttpGet("http://localhost:12688/Default2.aspx", para);
//return;
//para.Clear();
////

//para.Add("_method", "compute");
//para.Add("step", "2");
//req.HttpGet("http://localhost:12688/Default2.aspx", para);

//return;
////
//para.Clear();
//para.Add("_method", "compute");
//para.Add("step", "3");
//req.HttpGet("http://localhost:12688/Default2.aspx", para);

////
//para.Clear();
//para.Add("_method", "compute");
//para.Add("step", "4");
//req.HttpGet("http://localhost:12688/Default2.aspx", para);

////
//para.Clear();
//para.Add("_method", "compute");
//para.Add("step", "5");
//req.HttpGet("http://localhost:12688/Default2.aspx", para);

////
//para.Clear();
//para.Add("_method", "compute");
//para.Add("step", "6");
//req.HttpGet("http://localhost:12688/Default2.aspx", para);
}
protected void Page_Load(object sender, EventArgs e)
{
bb();

}
}
}
6.长连接客户端 LongConnectClinet
6.1 html
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="LongConnectClient.aspx.cs" Inherits="Comet_by_ASP.NET.LongConnectClient" %>

<!DOCTYPE html>

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title></title>
<style type="text/css">
*{ font-size:12px;}
#divResult
{
border:1px solid #000;
width:250px;
}
</style>
<script src="/Scripts/jquery.min.1.11.3.js"></script>
<script src="/Scripts/WebAsync.js"></script>
</head>
<body>
<form runat="server" id="form1">
广播内容:  <input type="text" id="content" /><br />
消息记录:
<div id="divResult"></div>
<input type="button" id="btnSend" value="广播" />
</form>
</body>
</html>
6.2 后台代码 这里的代码无关紧要
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;

namespace Comet_by_ASP.NET
{
public partial class LongConnectClient : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
//switch (Request["_method"])
//{
//    case "compute":
//        Page.ClientScript.RegisterClientScriptBlock(this.GetType(), Guid.NewGuid().ToString(), "<script>wait();send();</script>");
//        break;
//}
}
}
}

7.web.config
<system.webServer>
<modules runAllManagedModulesForAllRequests="true">
<remove name="FormsAuthentication" />
<remove name="ApplicationInsightsWebTracking" />
<add name="ApplicationInsightsWebTracking" type="Microsoft.ApplicationInsights.Web.ApplicationInsightsHttpModule, Microsoft.AI.Web" preCondition="managedHandler" />
</modules>
<handlers>
<add name="comet_broadcast" path="comet_broadcast.asyn" type="Handle.WebAsnyHandler" verb="POST,GET"/>
</handlers>
<validation validateIntegratedModeConfiguration="false" />
</system.webServer>
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: