现在的位置: 首页 > 综合 > 正文

wininet函数

2013年08月11日 ⁄ 综合 ⁄ 共 4370字 ⁄ 字号 评论关闭

1. 几个wininet函数。

URLDownloadToFile:给一个文件的url,就可以把文件下载下来,需要差数可以只有两个,url和文件保存的路径。该函数封装了http,ftp,gppher协议的函数,只要是正确的url都可以下载。

URLDownloadToFile拆分为三个函数:InternetOpen,InternetOpenUrl和InternetReadFile,InternetOpenUrl也是一个封装好了的函数,它也不管具体的协议内容。InternetOpenUrl返回一个HINTERNET句柄,该句柄作为HttpQueryInfo的入参,可以得到相关的信息,如文件的长度,文件修改的日期等。该句柄同时作为InternetReadFile的入参,InternetReadFile将文件下载到一个申请好的缓冲区中。

如果是http协议,InternetOpenUrl可以分解为InternetConnect,HttpOpenRequest,HttpSendRequest。InternetConnect负责连接服务器,HttpOpenRequest去创建一个请求句柄并且把参数存储在句柄中。HttpSendRequest把请求参数送到HTTP服务器。

几个可能会遇到,并且比较郁闷的问题。

1. HttpOpenRequest的问题
HttpOpenRequest的时候如果代码像下面这样写,一般不会出现什么问题。

HINTERNET hRequest = HttpOpenRequest(hConnect,
    "GET",
    pszLoctionFilePath,
    HTTP_VERSION,
    NULL,
    (const char **)p,
    0,
    1);

倒数第二个参数:IN DWORD dwFlags,msdn上说明:dwFlags Internet flag values. Can be any of the following values: ……
看上去如果是0的话,应该没有什么问题。但我的问题就出在这里。
参数为0的话,就会在第二次访问同一个url(不同的url不会有问题)的时候,HttpQueryInfo会失败, GetLastError()为12150:Header Not Found。这个时候如果打开IE选项,general->delete->delete files。就好了。我用程序删除缓冲区里的全部文件,没有用。非得手动点击一下delete files。这个问题产生的原因还没有找到,如果有谁遇到过同样的问题,麻烦告诉我一声。

倒数第三个参数,我的写法是:
char   szHead[] = "Accept: */*/r/n/r/n";
char **p = new char*[2];*p = szHead;*(p+1) = NULL;
之后倒数第三个参数为:(const char **)p,这样写不会有错。
如果写成(const char **)&szHead,程序不会报错,但debug调试的话,会有First-chance exception in HttpAndFtpTest.exe (KERNEL32.DLL): 0xC0000005: Access Violation.的警告,这是因为强制把一个1维数组变成2维数组,它的第二个数组没有'/0'结尾所导致的访问冲突。

2. 122错误

HttpOpenRequest之后报122:The data area passed to a system call is too small. 错误,原因没有找到。但程序不会有错误,也没有警告。

3. 各个过程花费时间

InternetOpen,InternetConnect,HttpOpenRequest,HttpQueryInfo基本上不花时间。HttpSendRequest和InternetReadFile,占用整个下载过程的绝大部分时间。

4. IE请求对应的程序的写法

http://www.abc.com/123/edf.asp?Key=login&login=2&password=1
对应的IE请求

// 连接服务器
HINTERNET hConnect = InternetConnect(hSession,
    ServerName,
    INTERNET_DEFAULT_HTTP_PORT,
    NULL,
    NULL,
    INTERNET_SERVICE_HTTP,
    0,
    1);
ServerName为www.abc.com

// 创建一个请求
HINTERNET hRequest = HttpOpenRequest(hConnect,
    Method,
    FormAction,
    HTTP_VERSION,
    NULL,
    (const char**)&accept,
    0,
    1);
Method为"GET"
FormAction为/123/edf.asp
BOOL bSeccuss = HttpSendRequest( hRequest, hdrs, strlen(hdrs), frmdata, strlen(frmdata))
frmdata为Key=login&login=2&password=1。

5. 删除IE缓存的函数

void   ClearInternetCache()  
{  
DWORD   dwNeeded   =   0;  
FindFirstUrlCacheEntry(NULL,   NULL,   &dwNeeded);  

if   (GetLastError()   ==   ERROR_INSUFFICIENT_BUFFER)  
{  
 unsigned   char   *buffer   =   new   unsigned   char[dwNeeded];  
 try  
 {  
  LPINTERNET_CACHE_ENTRY_INFO   lpicei   =  
  reinterpret_cast<LPINTERNET_CACHE_ENTRY_INFO>(buffer);  
  HANDLE   HFind   =     FindFirstUrlCacheEntry(NULL,   lpicei,   &dwNeeded);  
  DeleteUrlCacheEntry(lpicei->lpszSourceUrlName);  

  bool   no_more_files   =   false;  
  while   (!no_more_files)  
  {  
   if   (FindNextUrlCacheEntry(HFind,   lpicei,   &dwNeeded))  
   {  
    DeleteUrlCacheEntry(lpicei->lpszSourceUrlName);  
   }  
   else   switch   (GetLastError())  
   {  
    case   ERROR_INSUFFICIENT_BUFFER:  
    {  
     delete   []   buffer;  
     buffer   =   new   unsigned   char[dwNeeded];  
     lpicei   =   reinterpret_cast<LPINTERNET_CACHE_ENTRY_INFO>(buffer);  
     break;  
    }  
    default:  
    {  
     no_more_files   =   true;  
     break;  
    }  
   }  
  }
  FindCloseUrlCache(HFind);
 }  
 catch   (...)  
 {  
  delete   []   buffer;  
 }  
 delete   []   buffer;                  
}  
}

6. http和https的请求

InternetConnect 的第三个参数,INTERNET_DEFAULT_HTTP_PORT改为INTERNET_DEFAULT_HTTPS_PORT
HttpOpenRequest 的第七个参数 多了一个INTERNET_FLAG_SECURE 选项

还有一个自动安装证书的代码以前做过,现在找不到了。 

7. 更好的InternetOpen方法

DWORD dwFlags = 1;
InternetGetConnectedState(&dwFlags, 0);
if(!(dwFlags & INTERNET_CONNECTION_PROXY))
 *hSession = InternetOpenA("MyAgent", INTERNET_OPEN_TYPE_PRECONFIG_WITH_NO_AUTOPROXY, NULL, NULL, 0);
else
 *hSession = InternetOpenA("MyAgent", INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0);
if (*hSession)
 return TRUE;
else
 return FALSE;

8. 下载文件的函数
UINT InternetGetFile (HINTERNET IN hConnect, // Handle from InternetOpen()
                 LPCSTR szFileName)
{
 FILE * pFile;
 if  ( !(pFile = fopen (szFileName, "wb" ) ) )
 {
  return INTERNET_ERROR_FILEOPEN;
 }
 VOID* szTemp[16384];
 DWORD dwSize;
 while (TRUE)
 {
  // Keep coping in 16 KB chunks, while file has any data left.
  // Note: bigger buffer will greatly improve performance.
  if (!InternetReadFile (hConnect, szTemp, 16384,  &dwSize) )
  {
   fclose (pFile);
   return INTERNET_ERROR_READFILE;
  }
  if (!dwSize)
   break;  // Condition of dwSize=0 indicate EOF. Stop.
  else
   fwrite(szTemp, sizeof (char), dwSize , pFile);
 }   // do
 fflush (pFile);
 fclose (pFile);
 return 0;
}

9. 设置internet session

如果要设置internet session及其他参数,可以调用InternetSetOption。

抱歉!评论已关闭.