HttpWebRequest 的一个 异步封装

来源:互联网 发布:linux 创建多级目录 编辑:程序博客网 时间:2024/05/18 17:45

相信大家对HttpWebRequest这个类应该非常熟悉了吧。主要用它来模拟http请求,在有些时候我们需要用到它的异步处理,每次用的时候都要写很多代码,于是今天把它简单的封装了一下。虽然在C#4和C#5中它提供了很新方法是的异步更加简单,但是在一些老项目(还在用vs2005)上我们只能用C#2.0的语法来实现它的异步功能。

如图1,这里的RequestInfo类是请求信息的一个封装,ResponseInfo类是返回对象的一个封装,StateObject是一个内部状态保存对象类(我们不需要关心),RequestHttpWebRequest是HttpWebRequest的一个封装类,只有一个公共方法:

    public void GetResponseAsync(RequestInfo info, Action<ResponseInfo> act)

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对象。
说说简单的调用吧

 

整个调用是不是很简单啊!有不对的地方欢迎大家拍砖!