HttpWebRequest 的异步封装

HttpWebRequest 的一个 异步封装 里面提到了对HttpWebRequest的异步封装,但是如果用户不断的创建实例,那么就会有很对实例在内存中,这样是不可取,于是乎我们创建一个对象池来来管理对象的使用。因此我们需要给对象添加一属性IsBusy来标记该对象向现在是否有任务。然后我们创建一个RequestFactory来管理对象。修改后的带代码:

using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using System.Data;
using System.Data.OleDb;
using System.Net;
using System.Xml;
using System.Net.Security;
using System.Security.Cryptography.X509Certificates;

namespace HttpRequest
{
    [Serializable]
    public class RequestInfo
    {
        public RequestInfo(string url)
        {
            Url = url;
            AllowAutoRedirect = true;
        }
        public string Url { private set; get; }
        public byte[] PostData { set; get; }
        public WebHeaderCollection Headers { set; get; }
        public bool AllowAutoRedirect { set; get; }
        public Dictionary<string, string> ExternalData { set; get; }
    }

    [Serializable]
    public class ResponseInfo
    {
        public RequestInfo RequestInfo { set; get; }
        public Stream ResponseContent { set; get; }
        public HttpStatusCode StatusCode { set; get; }
        public WebHeaderCollection Headers { set; get; }
        public string GetString(Encoding coding)
        {
            StringBuilder str = new StringBuilder();
            Stream sr = ResponseContent;
            sr.Seek(0, SeekOrigin.Begin);
            byte[] data = new byte[1024 * 1024];
            int readcount = sr.Read(data, 0, data.Length);
            while (readcount > 0)
            {
                str.Append(coding.GetString(data, 0, readcount));
                readcount = sr.Read(data, 0, data.Length);
            }
            return str.ToString();
        }
    }

    internal class StateObject
    {
        public byte[] Buffer { set; get; }
        public ResponseInfo ResponseInfo { set; get; }
        public Stream ReadStream { set; get; }
        public HttpWebRequest HttpWebRequest { set; get; }
        public Action<ResponseInfo> Action { set; get; }
        public bool IsBusy { set; get; }

    }

    public class RequestHttpWebRequest
    {
        static RequestHttpWebRequest()
        {
            ServicePointManager.DefaultConnectionLimit = 100;
        }
        public RequestHttpWebRequest()
        {
            ServicePointManager.ServerCertificateValidationCallback = new RemoteCertificateValidationCallback(CheckValidationResult);
        }
        private bool CheckValidationResult(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors errors)
        {
            //直接确认,否则打不开  
            return true;
        }
        public void GetResponseAsync(RequestInfo info, Action<ResponseInfo> act)
        {
            HttpWebRequest webRequest;
            StateObject state;
            InitWebRequest(info, act, out webRequest, out state);
            try
            {
                if (info.PostData != null && info.PostData.Length > 0)
                {
                    webRequest.Method = "POST";
                    webRequest.ContentType = "application/x-www-form-urlencoded";
                    webRequest.BeginGetRequestStream(EndRequest, state);
                }
                else
                {
                    webRequest.BeginGetResponse(EndResponse, state);
                }

            }
            catch (Exception ex)
            {
                HandException(ex, state);
            }
        }
        void EndRequest(IAsyncResult ar)
        {
            StateObject state = ar.AsyncState as StateObject;
            try
            {
                HttpWebRequest webRequest = state.HttpWebRequest as HttpWebRequest;
                using (Stream stream = webRequest.EndGetRequestStream(ar))
                {
                    byte[] data = state.ResponseInfo.RequestInfo.PostData;
                    stream.Write(data, 0, data.Length);
                }
                webRequest.BeginGetResponse(EndResponse, state);

            }
            catch (Exception ex)
            {
                HandException(ex, state);
            }
        }
        void EndResponse(IAsyncResult ar)
        {
            StateObject state = ar.AsyncState as StateObject;
            try
            {
                HttpWebResponse webResponse = state.HttpWebRequest.EndGetResponse(ar) as HttpWebResponse;
                state.ResponseInfo.StatusCode = webResponse.StatusCode;
                state.ResponseInfo.Headers = new WebHeaderCollection();
                foreach (string key in webResponse.Headers.AllKeys)
                {
                    state.ResponseInfo.Headers.Add(key, webResponse.Headers[key]);
                }
                state.ReadStream = webResponse.GetResponseStream();
                state.ReadStream.BeginRead(state.Buffer, 0, state.Buffer.Length, ReadCallBack, state);
            }
            catch (Exception ex)
            {
                HandException(ex, state);

            }
        }
        void ReadCallBack(IAsyncResult ar)
        {
            StateObject state = ar.AsyncState as StateObject;
            try
            {
                int read = state.ReadStream.EndRead(ar);
                if (read > 0)
                {
                    state.ResponseInfo.ResponseContent.Write(state.Buffer, 0, read);
                    state.ReadStream.BeginRead(state.Buffer, 0, state.Buffer.Length, ReadCallBack, state);
                }
                else
                {
                    state.ReadStream.Close();
                    state.HttpWebRequest.Abort();
                    if (state.Action != null)
                    {
                        state.Action(state.ResponseInfo);
                    }
                    state.IsBusy = false;
                }
            }
            catch (Exception ex)
            {
                HandException(ex, state);
            }
        }
        private void InitWebRequest(RequestInfo info, Action<ResponseInfo> act, out HttpWebRequest webRequest, out StateObject state)
        {

            webRequest = HttpWebRequest.CreateDefault(new Uri(info.Url)) as HttpWebRequest;
            webRequest.KeepAlive = true;
            webRequest.AllowAutoRedirect = info.AllowAutoRedirect;
            if (info.Headers != null && info.Headers.Count > 0)
            {
                foreach (string key in info.Headers.Keys)
                {
                    webRequest.Headers.Add(key, info.Headers[key]);
                }
            }
            //webRequest.Proxy = WebProxy.GetDefaultProxy();
            //webRequest.Proxy.Credentials = CredentialCache.DefaultCredentials;  
            // webResponse.Headers.Get("Set-Cookie");
            state = new StateObject
            {
                Buffer = new byte[1024 * 1024],
                HttpWebRequest = webRequest,
                Action = act,
                IsBusy = true,
                ResponseInfo = new ResponseInfo
                {
                    RequestInfo = info,
                    ResponseContent = new MemoryStream()
                }
            };
        }
        StateObject State { set; get; }
        public bool IsBusy
        {
            get
            {
                if (State != null)
                    return State.IsBusy;
                return false;
            }
        }
        private void HandException(Exception ex, StateObject state)
        {
            string message = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") + " : " + state.ResponseInfo.RequestInfo.Url + " : " + ex.Message;
            Console.WriteLine(message);
            //LogManager.LogException(message);
        }
    }
}
View Code
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;

namespace HttpRequest
{
    public  class RequestFactory
    {
        static RequestFactory()
        {
            MaxRequestCount = 10;
            ThreadPool.QueueUserWorkItem(new WaitCallback(Process));
        }
        class RequestTask
        {
            public RequestInfo Request { set; get; }
            public Action<ResponseInfo> Action { set; get; }
        }

        static List<RequestTask> requestTask = new List<RequestTask>();
        static readonly object Lockobj = new object();
        static List<RequestHttpWebRequest> Handlers = new List<RequestHttpWebRequest>();

        public static void AddRequestTask(RequestInfo info, Action<ResponseInfo> act)
        {
            if (!string.IsNullOrEmpty(info.Url))
            {
                lock (Lockobj)
                {
                    requestTask.Add(new RequestTask() { Request = info, Action = act });
                }
            }
        }

        private static RequestHttpWebRequest GetAvailableHttpRequest()
        {
            RequestHttpWebRequest handler = null;
            for (int i = 0; i < Handlers.Count; i++)
            {
                if (!Handlers[i].IsBusy)
                {
                    handler = Handlers[i];
                    break;
                }
            }
            if (handler != null)
                return handler;
            if (Handlers.Count < MaxRequestCount)
            {
                handler = new RequestHttpWebRequest();
                lock (Lockobj)
                {
                    Handlers.Add(handler);
                }
                return handler;
            }
            Thread.Sleep(100);
            return GetAvailableHttpRequest();
        }

        private static RequestTask GetTask()
        {
            RequestTask task = null;
            if (requestTask.Count > 0)
            {
                lock (Lockobj)
                {
                    task = requestTask[0];
                    requestTask.RemoveAt(0);
                }
                return task;
            }
            else if (Closed)
            {
                return null;
            }
            else
            {
                Thread.Sleep(10);
                while (task == null)
                {
                    return GetTask();
                }

            }
            return task;
        }

        private static void Process(object obj)
        {
            while (!Closed || requestTask.Count > 0)
            {
                RequestHttpWebRequest handler = GetAvailableHttpRequest();
                RequestTask task = GetTask();
                if (task != null && handler != null)
                {
                    handler.GetResponseAsync(task.Request, task.Action);
                }
            }
            Thread.Sleep(10);
        }

        static int MaxRequestCount { set; get; }
        static bool Closed { set; get; }

    }
}
View Code

当然调用代码页非常简单:

   RequestInfo info = new RequestInfo("http://www.baidu.com/");
            Action<ResponseInfo> act=new Action<ResponseInfo>(x=>{
            Console.Write(x.GetString(Encoding.UTF8));
            });
            RequestFactory.AddRequestTask(info, act);

当然实际上应该把该程序部署成windows服务,他需要一直运行。

实际应该把

 static RequestFactory()
        {
            MaxRequestCount = 10;
            ThreadPool.QueueUserWorkItem(new WaitCallback(Process));
        }

抽取出来,这里只是演示,才把它放到构造函数里面。

有不对的地方还请大家拍砖!

 


<script type="text/javascript"> </script><script type="text/javascript" src="http://pagead2.googlesyndication.com/pagead/show_ads.js"></script>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值