天天看點

WinInet程式設計詳解

一般而言,開發Internet服務用戶端程式的目的是通過Internet協定(HTTP,FTP)擷取網絡資料源的資訊,微軟提供了專門的Win32 Internet擴充接口,也就是WinInet。

1使用Win API函數開發用戶端程式

一般流程是,首先通過InternetOpen()函數建立位于根部的HINTERNET句柄,然後才能進一步建立HTTP、FTP會話,使用InternetConnect()函數建立一個指定的會話,初始化HTTP、FTP會話(根據指定的參數決定),并建立一個根句柄的分支,HttpOpenRequest()、FtpOpenFile()、FtpFindFirstFile()等函數将使用InternetConnect()所建立的句柄,建立到指定站點的連接配接。例子代碼如下:

bool testFtpDownload ()

{

    // 建立會話

    HINTERNET hInternet;

    hInternet = InternetOpen("", INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0);

    if(hInternet == NULL) return false;

    // 建立連接配接

    HINTERNET hConnect;

    hConnect = InternetConnect(hInternet, "112.128.125.11", INTERNET_INVALID_PORT_NUMBER,

       "", "", INTERNET_SERVICE_FTP, INTERNET_FLAG_PASSIVE, 0);

    if(hInternet == NULL) { InternetCloseHandle(hInternet); return false; }

    HINTERNET hFtpFile;

    hFtpFile = FtpOpenFile(hConnect, "common/ Essential C++中文版.pdf", GENERIC_READ, FTP_TRANSFER_TYPE_BINARY|INTERNET_FLAG_RELOAD, NULL);

    if(hFtpFile == NULL) {   InternetCloseHandle(hConnect); InternetCloseHandle(hInternet); return false; }

    char buf[1024];

    DWORD buf_len = 1024;

    DWORD buf_read = 1024;

    FILE *fp = fopen("e:\\test.pdf", "wb");

    while(1)

    {

       InternetReadFile(hFtpFile, buf, buf_len, &buf_read);

       if(buf_read == 0) break;

       fwrite(buf, 1, buf_read, fp);

    }

    fclose(fp);

    InternetCloseHandle(hFtpFile);

    InternetCloseHandle(hConnect);

    InternetCloseHandle(hInternet);

    return true;

}

bool testHttpDownload()

{

    // 建立會話

    HINTERNET hInternet;

    hInternet = InternetOpen("", INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0);

    if(hInternet == NULL) return false;

    // 建立連接配接

    HINTERNET hConnect;

    hConnect = InternetConnect(hInternet, "hi.baidu.com", INTERNET_INVALID_PORT_NUMBER,

       "", "", INTERNET_SERVICE_HTTP, INTERNET_FLAG_PASSIVE, 0);

    if(hInternet == NULL) { InternetCloseHandle(hInternet); return false; }

    HINTERNET httpFile;

   httpFile = HttpOpenRequest(hConnect, "GET", "vc_net/blog/item/2d830208fe388bc063d986b2.html", HTTP_VERSION, NULL, 0, INTERNET_FLAG_NO_UI | INTERNET_FLAG_DONT_CACHE, 1);

    if(httpFile == NULL) {   InternetCloseHandle(hConnect); InternetCloseHandle(hInternet); return false; }

    HttpSendRequest(httpFile, NULL, NULL, 0, 0);

    char buf[1024];

    DWORD buf_len = 1024;

    DWORD buf_read = 1024;

    FILE *fp = fopen("e:\\test.txt", "wb");

    while(1)

    {

       InternetReadFile(httpFile, buf, buf_len, &buf_read);

       if(buf_read == 0) break;

       fwrite(buf, 1, buf_read, fp);

    }

    fclose(fp);

    InternetCloseHandle(httpFile);

    InternetCloseHandle(hConnect);

    InternetCloseHandle(hInternet);

    return true;

}

2.使用mfc類開發用戶端程式

網絡用戶端開發的要點是Internet Session,而mfc将Internet Session作為CInternetSession類的對象來實作,需要包含頭檔案#include <afxinet.h>

大多數Internet Session都需要與伺服器進行讀寫資料的操作,這就需要CInternetSession對象與一個CInternetFile對象的協同工作,即必須建立一個CInternetFile執行個體或者其子類CHttpFile的對象。建立CInternetFile對象有兩種方法:

1)直接調用CInternetSession::OpenURL函數,該函數打開一個到URL的連接配接,并傳回一個隻讀的CInternetFile對象.它還可以操作本地檔案(由URL資源“file://”标志),但是傳回一個CStdioFile對象。

2)調用相應服務協定類的打開函數

通過CInternetSession::GetHttpConnection, CInternetSession::GetFtpConnection建立的伺服器連接配接對話,則必須調用CHttpConnection::OpenRequest,CFtpConnection::OpenFile函數,傳回一個CHttpFile、CFtpFile對象。

2.1使用WinInet通路HTTP伺服器

最簡單的方法是建立CInternetSession對象,以HTTP站點的URL參數調用OpenURL(),傳回一個CInternetFile檔案句柄,以此句柄操作檔案。例如代碼如下:

bool DownloadHtml(const string& url, const string& filename)

{

    char buf[1000];

    FILE* fp = fopen(filename.c_str(),"wb");

    if (NULL == fp)

       return false;

    DWORD nRead = 0;

    CInternetSession localsession;

    CInternetFile* webfile = NULL;

    try

    {

       webfile = (CInternetFile*)localsession.OpenURL(url.c_str());

    }

    catch(CInternetException* pException)

    {

       webfile = NULL;

       pException->Delete();

    }

    while((nRead = webfile->Read(buf,1000)) > 0) 

       fwrite(buf, 1, nRead, fp);

    fclose(fp);

    delete webfile;

    localsession.Close();

    return true;

}

2.2使用WinInet通路FTP伺服器

常使用CFtpConnection類,具體方法如下:

調用函數CInternetSession::GetFtpConnection()建立連接配接,該函數所需的參數依次為FTP站點域名、使用者名、密碼、FTP服務端口号(預設為21)、通路模式(被動或主動)。

連接配接建立完成後,用CFtpConnection類的方法操作遠端FTP伺服器的檔案系統,具體如下:

SetCurrentDirectory(GetCurrentDirectory)設定(擷取)此連接配接的FTP目錄。

RemoveDirectory(CreateDirectory)删除(建立)目錄

Rename、Remove、PutFile、GetFile、OpenFile等對檔案進行更名、删除、上傳、下載下傳及打開等操作。

用Close函數關閉與FTP伺服器的連接配接。

例子代碼如下:

bool DownloadFile(const string& url, const string& filename)

{

    CInternetSession localsession(L"my session");

    CFtpConnection* ftp= localsession.GetFtpConnection(L"122.118.125.11",L"",L"",21);

//  ftp->GetFile(L"test/資訊.txt",L"e:\\tt.txt");

    ftp->PutFile(L"e:\\tjl.txt",L"common/test.txt");

    ftp->Close();

    localsession.Close();

    return true;

}