HttpWebRequest 的异步封装

来源:互联网 发布:网络安全教育读后感 编辑:程序博客网 时间:2024/06/05 18:52

在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"><!--google_ad_client = "ca-pub-1944176156128447";/* cnblogs 首页横幅 */google_ad_slot = "5419468456";google_ad_width = 728;google_ad_height = 90;//--></script><script type="text/javascript" src="http://pagead2.googlesyndication.com/pagead/show_ads.js"></script>
原创粉丝点击