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

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>

 

posted on 2017-06-10 13:45  听哥哥的话  阅读(311)  评论(0编辑  收藏  举报

导航