C#调用Wininet的相关问题,在线等!

ismycxp 2011-05-28 10:19:36
经测试,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,为什么呢?哪里出错了???

如何解决这个问题,请高手解答!
...全文
466 6 打赏 收藏 转发到动态 举报
写回复
用AI写文章
6 条回复
切换为时间正序
请发表友善的回复…
发表回复
ArcRain 2012-12-09
  • 打赏
  • 举报
回复
建议看下MSDN的说明:http://msdn.microsoft.com/en-us/library/windows/desktop/aa384247(v=vs.85).aspx 特别是这段话: 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.
幸福海 2012-12-08
  • 打赏
  • 举报
回复
String lpszHeaders = "Content-Type: application/x-www-form-urlencoded"; bool sendResult = HttpSendRequest(hRequest, lpszHeaders, -1L, PostData, PostData.Length); 这是相关POST的代码
幸福海 2012-12-08
  • 打赏
  • 举报
回复
用它做了个小东西,get请求没有问题,但是post的时候,出错不行,请大神出个POST的方法
lostgdi 2011-09-10
  • 打赏
  • 举报
回复
thank for you sharing
Maravel 2011-07-01
  • 打赏
  • 举报
回复
经典的东西啊
ArcRain 2011-05-28
  • 打赏
  • 举报
回复
InternetOpen和InternetConnect改下试试。
InternetOpen("asdf\0", INTERNET_OPEN_TYPE_PRECONFIG, null, null, 0);
InternetConnect(hSession,uri.Host,(uint)uri.Port,null,null,INTERNET_SERVICE_HTTP,0,0);

110,566

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Web++
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧