WinInet 基础知识

可以使用 WinInet 添加 FTP 支持,以便从应用程序中下载和上传文件。 可以替代 OnStatusCallback,并使用 dwContext 参数在搜索和下载文件时向用户提供进度信息。

本文包含以下主题:

下面的代码摘录演示如何创建简单的浏览器、下载网页、通过 FTP 传输文件以及搜索 gopher 文件。 它们并不充当完整示例,并非全部包含异常处理。

有关 WinInet 的其他信息,请参阅 Win32 Internet 扩展 (WinInet)

创建非常简单的浏览器

#include <afxinet.h>

void DisplayPage(LPCTSTR pszURL)
{
   CInternetSession session(_T("My Session"));
   CStdioFile *pFile = NULL;
   CHAR szBuff[1024];
   //use a URL and print a Web page to the console
   pFile = session.OpenURL(pszURL);
   while (pFile->Read(szBuff, 1024) > 0)
   {
      printf_s("%1023s", szBuff);
   }
   delete pFile;
   session.Close();
}

下载网页

//this code excerpt also demonstrates try/catch exception handling
#include <afxinet.h>

void DisplayHttpPage(LPCTSTR pszServerName, LPCTSTR pszFileName)
{
   CInternetSession session(_T("My Session"));
   CHttpConnection *pServer = NULL;
   CHttpFile *pFile = NULL;
   try
   {
      CString strServerName;
      INTERNET_PORT nPort = 80;
      DWORD dwRet = 0;

      pServer = session.GetHttpConnection(pszServerName, nPort);
      pFile = pServer->OpenRequest(CHttpConnection::HTTP_VERB_GET, pszFileName);
      pFile->SendRequest();
      pFile->QueryInfoStatusCode(dwRet);

      if (dwRet == HTTP_STATUS_OK)
      {
         CHAR szBuff[1024];
         while (pFile->Read(szBuff, 1024) > 0)
         {
            printf_s("%1023s", szBuff);
         }
      }
      delete pFile;
      delete pServer;
   }
   catch (CInternetException *pEx)
   {
      //catch errors from WinInet
      TCHAR pszError[64];
      pEx->GetErrorMessage(pszError, 64);
      _tprintf_s(_T("%63s"), pszError);
   }
   session.Close();
}

通过 FTP 传输文件

#include <afxinet.h>

void GetFtpFile(LPCTSTR pszServerName, LPCTSTR pszRemoteFile, LPCTSTR pszLocalFile)
{
   CInternetSession session(_T("My FTP Session"));
   CFtpConnection *pConn = NULL;

   pConn = session.GetFtpConnection(pszServerName);
   //get the file
   if (!pConn->GetFile(pszRemoteFile, pszLocalFile))
   {
      //display an error
   }
   delete pConn;
   session.Close();
}

检索 Gopher 目录

#include <afxinet.h>

void RetrieveGopherFile(LPCTSTR pszGopherSite, LPCTSTR pszFile)
{
   CInternetSession session(_T("My Gopher Session"));
   CGopherConnection *pConn = NULL;
   CGopherFileFind *pFile;

   pConn = session.GetGopherConnection(pszGopherSite);
   pFile = new CGopherFileFind(pConn);
   BOOL bFound = pFile->FindFile(pszFile);
   while (bFound)
   {
      //retrieve attributes of found file
      bFound = pFile->FindNextFile();
   }
   delete pFile;
   delete pConn;
   session.Close();
}

使用 OnStatusCallback

使用 WinInet 类时,可以使用应用程序 CInternetSession 对象的 OnStatusCallback 成员检索状态信息。 如果你派生自己的 CInternetSession 对象、替代 OnStatusCallback 以及启用状态回调,则 MFC 会使用有关该 Internet 会话中所有活动的进度信息调用 OnStatusCallback 函数。

由于单个会话可以支持多个连接(在其生存期内,它们可能会执行许多不同的操作),因此 OnStatusCallback 需要一种机制来识别特定连接或事务的每个状态更改。 该机制由提供给 WinInet 支持类中的许多成员函数的上下文 ID 参数提供。 此参数始终为 DWORD 类型,并且始终名为 dwContext

分配给特定 Internet 对象的上下文仅用于标识该对象在 CInternetSession 对象的 OnStatusCallback 成员中引发的活动。 调用 OnStatusCallback 会接收多个参数;这些参数协同工作,告知应用程序哪个事务和连接的进度如何。

创建 CInternetSession 对象时,可以向构造函数指定 dwContext 参数。 CInternetSession 本身不使用上下文 ID;而是将上下文 ID 传递给任何未显式获取其自己的上下文 ID 的 InternetConnection 派生对象。 如果你未显式指定不同的上下文 ID,那么这些 CInternetConnection 对象进而会将上下文 ID 传递给它们创建的 CInternetFile 对象。 另一方面,如果你指定自己的特定上下文 ID,则对象及其执行的任何工作都会与该上下文 ID 关联。 你可以使用上下文 ID 标识在 OnStatusCallback 函数中提供给你的状态信息。

传输文件时显示进度信息

例如,如果你编写的应用程序会创建与 FTP 服务器的连接以读取文件,还会连接到 HTTP 服务器以获取网页,则你会使用一个 CInternetSession 对象、两个 CInternetConnection 对象(一个是 CFtpSession,另一个是 CHttpSession)以及两个 CInternetFile 对象(每个连接各一个)。 如果对 dwContext 参数使用默认值,则无法区分指示 FTP 连接进度的 OnStatusCallback 调用与指示 HTTP 连接进度的调用。 如果指定 dwContext ID(稍后可以在 OnStatusCallback 中对其进行测试),你会知道哪个操作生成了回调。

另请参阅

MFC Internet 编程基础知识
Win32 Internet 扩展 (WinInet)