preload preload preload preload

Jailu.Net.HttpHelper:网络请求类(新版)


27th 五月 2011 技术文章 0 Comments

最近,本人开发的小工具《开心城管》出了点问题,具体表现为:切换用户时,网络请求超时。一开始还以为是开心网做了什么限制,导致请求超时,后来利用Http Anylyzer发现,出现超时错误时,请求根本就没有发出。奇怪的问题,这到底是什么问题造成的呢?仔细检查了相关代码,没有什么发现,求助于搜索引擎后,找到了问题所在:HttpWebRequest在GetResponse之后,没有调用WebResponse.Close关掉请求。默认情况下,System.Net 对每个主机的每个应用程序使用两个连接,连接数超过两个时,就会出现请求超时的问题。通过设置应用程序的 ServicePoint 中的 ConnectionLimit 属性可增加最大连接数。设置 ServicePointManager.DefaultPersistentConnectionLimit 属性可增加连接数的默认值。

找到问题所在后,就是修改代码了。修改代码之前,准备参考一下其它人HttpHelper的写法,于是百度了一下,发现目前网上最流行的HttpHelper(http://win.51aspx.com/CV/QQWinFarm,HttpHelper.cs.html)居然是本人在两年多前编写的,只是作了些许不同的修改。虽然这两年,本人对HttpHelper作了不少修改,但总觉得不是太完美,于是重写了下,修复本文开头描述的Bug的同时,让HttpHelper更加灵活。下面是今天重写后的HttpHelper:

/*
 * Copyright (c) 2011 Jailu (Mr.Jailu@gmail.com)
 * Dual licensed under GPL V3 licenses.
 */

using System;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Net;
using System.Text;

namespace Jailu.Net
{
    public class HttpHelper
    {
        private CookieContainer _CookieContainer;
        public CookieContainer CookieContainer
        {
            get
            {
                return _CookieContainer;
            }
            set
            {
                _CookieContainer = value;
            }
        }

        private string _ContentType = "application/x-www-form-urlencoded; charset=UTF-8";
        public string ContentType
        {
            get
            {
                return _ContentType;
            }
            set
            {
                _ContentType = value;
            }

        }

        private string _Accept = "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8";
        public string Accept
        {
            get
            {
                return _Accept;
            }
            set
            {
                _Accept = value;
            }
        }

        private string _UserAgent = "Mozilla/5.0 (Windows NT 6.1; rv:2.0) Gecko/20100101 Firefox/4.0";
        public string UserAgent
        {
            get
            {
                return _UserAgent;
            }
            set
            {
                _UserAgent = value;
            }
        }

        private Encoding _Encoding = Encoding.GetEncoding("utf-8");
        public Encoding Encoding
        {
            get
            {
                return _Encoding;
            }
            set
            {
                _Encoding = value;
            }
        }

        private int? _RequestTimeOut;
        public int? RequestTimeOut
        {
            get
            {
                return _RequestTimeOut;
            }
            set
            {
                _RequestTimeOut = value;
            }
        }

        private IWebProxy _WebProxy;
        public IWebProxy WebProxy
        {
            get
            {
                return _WebProxy;
            }
            set
            {
                _WebProxy = value;
            }
        }

        public HttpHelper()
        {
            _CookieContainer = new CookieContainer();
        }

        public HttpHelper(CookieContainer cookieContainer)
        {
            _CookieContainer = cookieContainer;
        }

        public string DoRequest(string url, string postData = null, HttpRequestMethod requestMethod = HttpRequestMethod.Get, CookieContainer cookieContainer = null, Encoding encoding = null, Action<HttpWebRequest> resetHttpWebRequest = null)
        {
            var stream = this.DoRequestAsStream(url, postData, requestMethod, cookieContainer, encoding, resetHttpWebRequest);

            var streamReader = new StreamReader(stream, encoding ?? this.Encoding);

            var result = streamReader.ReadToEnd();

            streamReader.Close();
            stream.Close();

            return result;
        }

        public Bitmap DoRequestAsBitmap(string url, string postData = null, HttpRequestMethod requestMethod = HttpRequestMethod.Get, CookieContainer cookieContainer = null, Encoding encoding = null, Action<HttpWebRequest> resetHttpWebRequest = null)
        {
            var stream = this.DoRequestAsStream(url, postData, requestMethod, cookieContainer, encoding, resetHttpWebRequest);

            return new Bitmap(stream);
        }

        public MemoryStream DoRequestAsStream(string url, string postData = null, HttpRequestMethod requestMethod = HttpRequestMethod.Get, CookieContainer cookieContainer = null, Encoding encoding = null, Action<HttpWebRequest> resetHttpWebRequest = null)
        {
            HttpWebRequest httpWebRequest = (HttpWebRequest)HttpWebRequest.Create(url);
            httpWebRequest.CookieContainer = cookieContainer ?? this.CookieContainer;
            httpWebRequest.ContentType = this.ContentType;
            httpWebRequest.Accept = this.Accept;
            httpWebRequest.UserAgent = this.UserAgent;

            if (this.RequestTimeOut.HasValue)
            {
                httpWebRequest.Timeout = this.RequestTimeOut.Value;
            }

            if (this.WebProxy != null)
            {
                httpWebRequest.Proxy = this.WebProxy;
            }

            if (resetHttpWebRequest != null)
            {
                resetHttpWebRequest(httpWebRequest);
            }

            HttpWebResponse httpWebResponse;
            if (requestMethod == HttpRequestMethod.Post)
            {
                httpWebRequest.Method = "POST";

                byte[] postBytes = (encoding ?? this.Encoding).GetBytes(postData ?? string.Empty);
                httpWebRequest.ContentLength = postBytes.Length;

                Stream stream = httpWebRequest.GetRequestStream();
                stream.Write(postBytes, 0, postBytes.Length);
                stream.Close();
            }
            else
            {
                httpWebRequest.Method = "GET";
            }

            httpWebResponse = (HttpWebResponse)httpWebRequest.GetResponse();
            Stream responseStream = httpWebResponse.GetResponseStream();

            MemoryStream memoryStream = new MemoryStream();

            const int bufferLength = 1024;

            int actual;
            byte[] buffer = new byte[bufferLength];
            while ((actual = responseStream.Read(buffer, 0, bufferLength)) > 0)
            {
                memoryStream.Write(buffer, 0, actual);
            }

            memoryStream.Position = 0;

            responseStream.Close();
            httpWebResponse.Close();

            return memoryStream;
        }
    }

    public enum HttpRequestMethod
    {
        Get = 0,
        Post = 1,
    }
}

调用方法:

1. Get请求

var result = new HttpHelper().DoRequest("http://www.domain.com");

2. Post请求

var result = new HttpHelper().DoRequest(
    "http://www.domain.com/login.aspx",
    "username=jailu&password=123",
    HttpRequestMethod.Post
);

3. 高级用法

var result = new HttpHelper().DoRequest(
    "http://www.domain.com/login.aspx",
    "username=jailu&password=123",
    HttpRequestMethod.Post,
    new CookieContainer(),
    Encoding.GetEncoding("gb2312"),
    (request) =>
    {
        request.AllowAutoRedirect = false;
        request.Headers.Add("Accept-Encoding", "gzip, deflate");
    }
);

点击下载HttpHelper源码

Read More »