经测试,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,为什么呢?哪里出错了???如何解决这个问题,请高手解答!

解决方案 »

  1.   

    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);
      

  2.   

    用它做了个小东西,get请求没有问题,但是post的时候,出错不行,请大神出个POST的方法
      

  3.   

          String lpszHeaders = "Content-Type: application/x-www-form-urlencoded";        bool sendResult = HttpSendRequest(hRequest, lpszHeaders, -1L, PostData, PostData.Length);
    这是相关POST的代码
      

  4.   

    建议看下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.