相信大家对HttpWebRequest这个类应该非常熟悉了吧。主要用它来模拟http请求,在有些时候我们需要用到它的异步处理,每次用的时候都要写很多代码,于是今天把它简单的封装了一下。虽然在C#4和C#5中它提供了很新方法是的异步更加简单,但是在一些老项目(还在用vs2005)上我们只能用C#2.0的语法来实现它的异步功能。
如图1,这里的RequestInfo类是请求信息的一个封装,ResponseInfo类是返回对象的一个封装,StateObject是一个内部状态保存对象类(我们不需要关心),RequestHttpWebRequest是HttpWebRequest的一个封装类,只有一个公共方法:
public void GetResponseAsync(RequestInfo info, Action<ResponseInfo> act)
View Code
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; [Serializable] public class RequestInfo { public RequestInfo(string url) { Url = url; AllowAutoRedirect = true; } public string Url { 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 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); } } } 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, ResponseInfo = new ResponseInfo { RequestInfo = info, ResponseContent = new MemoryStream() } }; } 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); } }
这里的几个类及其属性都很好明白,我就不说了。只是大家要注意一点的是ResponseInfo中ResponseContent属性是服务器返回的数据流,这里它是一个MemoryStream对象。
说说简单的调用吧
整个调用是不是很简单啊!有不对的地方欢迎大家拍砖!