最近,本人开发的小工具《开心城管》出了点问题,具体表现为:切换用户时,网络请求超时。一开始还以为是开心网做了什么限制,导致请求超时,后来利用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");
}
);

最新评论