经测试,HttpWebRequest和自己封闭的HTTP Socket效率比不上windows api Wininet,获取同一网址的代码,wininet总是快人一步,而且有些服务器特别忙时,wininet也能获取到代码,不至于超时,于是我把wininet封装成一个c#类,如下:
using System;
using System.Collections.Generic;
using System.IO;
using System.Runtime.InteropServices;
using System.Text;namespace WinTest
{
class Wininet
{
public const uint INTERNET_OPEN_TYPE_PRECONFIG = 0;
public const uint INTERNET_OPEN_TYPE_DIRECT = 1;
public const uint INTERNET_OPEN_TYPE_GATEWAY = 2;
public const uint INTERNET_OPEN_TYPE_PROXY = 3;
//Service/Command types
public const uint INTERNET_SERVICE_HTTP = 3;
//Internet connection flags
public const uint INTERNET_FLAG_KEEP_CONNECTION = 0x400000;
public const uint INTERNET_FLAG_NO_CACHE_WRITE = 0x4000000;
public const uint INTERNET_FLAG_RELOAD = 0x80000000;
//addheaders flags
public const uint HTTP_ADDREQ_FLAG_ADD_IF_NEW = 0x10000000;
public const uint HTTP_ADDREQ_FLAG_ADD = 0x20000000;
public const uint HTTP_ADDREQ_FLAG_REPLACE = 0x80000000; public const string HTTP_VERSION = "HTTP/1.1"; [DllImport("kernel32.dll", CharSet = CharSet.Auto)]
public static extern uint GetLastError();
[DllImport("wininet.dll", CharSet = CharSet.Auto)]
public static extern IntPtr InternetOpen(string strAppName, ulong ulAccessType, string strProxy, string strProxyBypass, ulong ulFlags);
[DllImport("wininet.dll", CharSet = CharSet.Auto)]
public static extern IntPtr InternetConnect(IntPtr ulSession, string strServer, uint ulPort, string strUser, string strPassword, uint ulService, uint ulFlags, uint ulContext);
[DllImport("wininet.dll", CharSet = CharSet.Auto)]
public static extern bool InternetGetConnectedState(ref uint ulFlags, uint ulReserved);
[DllImport("wininet.dll", CharSet = CharSet.Auto)]
public static extern bool InternetCloseHandle(IntPtr ulSession); [DllImport("wininet.dll", CharSet = CharSet.Auto)]
public static extern bool HttpAddRequestHeaders(IntPtr hRequest, string szHeasers, uint headersLen, uint modifiers);
[DllImport("wininet.dll", CharSet = CharSet.Auto)]
public static extern IntPtr HttpOpenRequest(IntPtr hConnect, string szVerb, string szURI, string szHttpVersion, string szReferer, StringBuilder accetpType, uint dwflags, int dwcontext); [DllImport("wininet.dll", CharSet = CharSet.Auto)]
public static extern bool HttpSendRequest(IntPtr hRequest, string szHeaders, long headersLen, long options, long optionsLen); [DllImport("wininet.dll", CharSet = CharSet.Auto)]
public static extern bool InternetReadFile(IntPtr hRequest, byte[] pByte, int size, out int revSize); private Dictionary<string, string> headerList = new Dictionary<string, string>();
public void AddHeader(string header, string value)
{
headerList.Add(header, value);
} public string GetHtml(string url)
{
Uri uri = new Uri(url);
string strProxy = "";
string strProxyBypass = "";
IntPtr hSession = InternetOpen("asdf\0", INTERNET_OPEN_TYPE_PRECONFIG, strProxy, strProxyBypass, 0);
if (hSession == IntPtr.Zero)
{
throw new Exception("InternetOpen初始化链接失败!");
}
IntPtr hConnect = InternetConnect(hSession,
uri.Host,
(uint)uri.Port,
null,
null,
INTERNET_SERVICE_HTTP,
INTERNET_FLAG_KEEP_CONNECTION | INTERNET_FLAG_NO_CACHE_WRITE,
0);
if (hConnect == IntPtr.Zero)
{
throw new Exception("InternetConnect初始化链接失败!");
}
IntPtr hRequest = HttpOpenRequest(hConnect,
"GET",
uri.PathAndQuery,
HTTP_VERSION,
null,
null,
INTERNET_FLAG_RELOAD | INTERNET_FLAG_NO_CACHE_WRITE,
0);
if (hRequest == IntPtr.Zero)
{
throw new Exception("HttpOpenRequest打开链接失败!");
} //添加HTTP头
//foreach (KeyValuePair<string, string> kv in this.headerList)
//{
// HttpAddRequestHeaders(hRequest, kv.Key, (uint)kv.Key.Length, HTTP_ADDREQ_FLAG_ADD | HTTP_ADDREQ_FLAG_REPLACE);
//}
bool sendResult = HttpSendRequest(hRequest, null, 0, 0, 0);
//??????????这里的sendResult总是为false,为什么会这样,请高手解答????????????
if (sendResult == false)
{
throw new Exception("HttpSendRequest发送请求失败!");
}
int bufferSize = 1024;
int revSize = 0;
byte[] bytes = new byte[bufferSize];
MemoryStream ms = new MemoryStream();
while (true)
{
bool readResult = InternetReadFile(hRequest, bytes, bufferSize, out revSize);
if (readResult && revSize > 0)
{
ms.Write(bytes, 0, revSize);
}
else
{
break;
}
}
bool result1 = InternetCloseHandle(hRequest);
bool result2 = InternetCloseHandle(hConnect);
bool result3 = InternetCloseHandle(hSession);
return Encoding.GetEncoding("gb2312").GetString(ms.ToArray());
}
}
}调用代码:...
Wininet winnet = new Wininet();
//winnet.AddHeader("Accept-Language", "zh-cn");
//winnet.AddHeader("Accept-Encoding", "gzip,deflate");
string html = winnet.GetHtml(url);
...
问题出现了,每次执行到bool sendResult = HttpSendRequest(hRequest, null, 0, 0, 0);
这句的时候,总是返回false,为什么呢?哪里出错了???如何解决这个问题,请高手解答!
using System;
using System.Collections.Generic;
using System.IO;
using System.Runtime.InteropServices;
using System.Text;namespace WinTest
{
class Wininet
{
public const uint INTERNET_OPEN_TYPE_PRECONFIG = 0;
public const uint INTERNET_OPEN_TYPE_DIRECT = 1;
public const uint INTERNET_OPEN_TYPE_GATEWAY = 2;
public const uint INTERNET_OPEN_TYPE_PROXY = 3;
//Service/Command types
public const uint INTERNET_SERVICE_HTTP = 3;
//Internet connection flags
public const uint INTERNET_FLAG_KEEP_CONNECTION = 0x400000;
public const uint INTERNET_FLAG_NO_CACHE_WRITE = 0x4000000;
public const uint INTERNET_FLAG_RELOAD = 0x80000000;
//addheaders flags
public const uint HTTP_ADDREQ_FLAG_ADD_IF_NEW = 0x10000000;
public const uint HTTP_ADDREQ_FLAG_ADD = 0x20000000;
public const uint HTTP_ADDREQ_FLAG_REPLACE = 0x80000000; public const string HTTP_VERSION = "HTTP/1.1"; [DllImport("kernel32.dll", CharSet = CharSet.Auto)]
public static extern uint GetLastError();
[DllImport("wininet.dll", CharSet = CharSet.Auto)]
public static extern IntPtr InternetOpen(string strAppName, ulong ulAccessType, string strProxy, string strProxyBypass, ulong ulFlags);
[DllImport("wininet.dll", CharSet = CharSet.Auto)]
public static extern IntPtr InternetConnect(IntPtr ulSession, string strServer, uint ulPort, string strUser, string strPassword, uint ulService, uint ulFlags, uint ulContext);
[DllImport("wininet.dll", CharSet = CharSet.Auto)]
public static extern bool InternetGetConnectedState(ref uint ulFlags, uint ulReserved);
[DllImport("wininet.dll", CharSet = CharSet.Auto)]
public static extern bool InternetCloseHandle(IntPtr ulSession); [DllImport("wininet.dll", CharSet = CharSet.Auto)]
public static extern bool HttpAddRequestHeaders(IntPtr hRequest, string szHeasers, uint headersLen, uint modifiers);
[DllImport("wininet.dll", CharSet = CharSet.Auto)]
public static extern IntPtr HttpOpenRequest(IntPtr hConnect, string szVerb, string szURI, string szHttpVersion, string szReferer, StringBuilder accetpType, uint dwflags, int dwcontext); [DllImport("wininet.dll", CharSet = CharSet.Auto)]
public static extern bool HttpSendRequest(IntPtr hRequest, string szHeaders, long headersLen, long options, long optionsLen); [DllImport("wininet.dll", CharSet = CharSet.Auto)]
public static extern bool InternetReadFile(IntPtr hRequest, byte[] pByte, int size, out int revSize); private Dictionary<string, string> headerList = new Dictionary<string, string>();
public void AddHeader(string header, string value)
{
headerList.Add(header, value);
} public string GetHtml(string url)
{
Uri uri = new Uri(url);
string strProxy = "";
string strProxyBypass = "";
IntPtr hSession = InternetOpen("asdf\0", INTERNET_OPEN_TYPE_PRECONFIG, strProxy, strProxyBypass, 0);
if (hSession == IntPtr.Zero)
{
throw new Exception("InternetOpen初始化链接失败!");
}
IntPtr hConnect = InternetConnect(hSession,
uri.Host,
(uint)uri.Port,
null,
null,
INTERNET_SERVICE_HTTP,
INTERNET_FLAG_KEEP_CONNECTION | INTERNET_FLAG_NO_CACHE_WRITE,
0);
if (hConnect == IntPtr.Zero)
{
throw new Exception("InternetConnect初始化链接失败!");
}
IntPtr hRequest = HttpOpenRequest(hConnect,
"GET",
uri.PathAndQuery,
HTTP_VERSION,
null,
null,
INTERNET_FLAG_RELOAD | INTERNET_FLAG_NO_CACHE_WRITE,
0);
if (hRequest == IntPtr.Zero)
{
throw new Exception("HttpOpenRequest打开链接失败!");
} //添加HTTP头
//foreach (KeyValuePair<string, string> kv in this.headerList)
//{
// HttpAddRequestHeaders(hRequest, kv.Key, (uint)kv.Key.Length, HTTP_ADDREQ_FLAG_ADD | HTTP_ADDREQ_FLAG_REPLACE);
//}
bool sendResult = HttpSendRequest(hRequest, null, 0, 0, 0);
//??????????这里的sendResult总是为false,为什么会这样,请高手解答????????????
if (sendResult == false)
{
throw new Exception("HttpSendRequest发送请求失败!");
}
int bufferSize = 1024;
int revSize = 0;
byte[] bytes = new byte[bufferSize];
MemoryStream ms = new MemoryStream();
while (true)
{
bool readResult = InternetReadFile(hRequest, bytes, bufferSize, out revSize);
if (readResult && revSize > 0)
{
ms.Write(bytes, 0, revSize);
}
else
{
break;
}
}
bool result1 = InternetCloseHandle(hRequest);
bool result2 = InternetCloseHandle(hConnect);
bool result3 = InternetCloseHandle(hSession);
return Encoding.GetEncoding("gb2312").GetString(ms.ToArray());
}
}
}调用代码:...
Wininet winnet = new Wininet();
//winnet.AddHeader("Accept-Language", "zh-cn");
//winnet.AddHeader("Accept-Encoding", "gzip,deflate");
string html = winnet.GetHtml(url);
...
问题出现了,每次执行到bool sendResult = HttpSendRequest(hRequest, null, 0, 0, 0);
这句的时候,总是返回false,为什么呢?哪里出错了???如何解决这个问题,请高手解答!
InternetOpen("asdf\0", INTERNET_OPEN_TYPE_PRECONFIG, null, null, 0);
InternetConnect(hSession,uri.Host,(uint)uri.Port,null,null,INTERNET_SERVICE_HTTP,0,0);
这是相关POST的代码
特别是这段话:
There two versions of HttpSendRequest —HttpSendRequestA (used with ANSI builds) and HttpSendRequestW (used with Unicode builds). If dwHeadersLength is -1L and lpszHeaders is not NULL, the following will happen: If HttpSendRequestA is called, the function assumes that lpszHeaders is zero-terminated (ASCIIZ), and the length is calculated. If HttpSendRequestW is called, the function fails with ERROR_INVALID_PARAMETER.