赞
踩
在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); } } }
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; } } }
当然调用代码页非常简单:
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));
}
抽取出来,这里只是演示,才把它放到构造函数里面。
有不对的地方还请大家拍砖!
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。