zoukankan      html  css  js  c++  java
  • HttpWebRequest 的一个 异步封装

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

     

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

  • 相关阅读:
    Java8新特性简介
    责任链模式
    Bean的生命周期
    APP中https证书有效性验证引发安全问题(例Fiddler可抓https包)
    程序员成长指南
    Go 代码性能优化小技巧
    Go slice 扩容机制分析
    一次 Go 程序 out of memory 排查及反思
    curl 常用操作总结
    Go benchmark 详解
  • 原文地址:https://www.cnblogs.com/majiang/p/3049622.html
Copyright © 2011-2022 走看看