Bagikan melalui


Common Functions (Windows Internet)

Protokol Internet yang berbeda (seperti ftp dan http) menggunakan beberapa fungsi WinINet yang sama untuk menangani informasi di Internet. Fungsi umum ini menangani tugas mereka secara konsisten, terlepas dari protokol tertentu yang diterapkan. Aplikasi dapat menggunakan fungsi-fungsi ini untuk membuat fungsi tujuan umum yang menangani tugas di berbagai protokol (seperti membaca file untuk ftp dan http).

Fungsi umum menangani tugas-tugas berikut:

Menggunakan Common Functions

Tabel berikut mencantumkan fungsi umum yang disertakan dalam fungsi WinINet. Fungsi umum dapat digunakan pada berbagai jenis handel HINTERNET atau dapat digunakan selama berbagai jenis sesi.

Fungsi Deskripsi
InternetFindNextFile Melanjutkan enumerasi atau pencarian file. Memerlukan handel yang dibuat olehFtpFindFirstFile , atau fungsi InternetOpenUrl.
InternetLockRequestFile Memungkinkan pengguna untuk menempatkan kunci pada file yang sedang digunakan. Fungsi ini memerlukan handel yang dikembalikan olehFtpOpenFile , httpOpenRequest, atau fungsi InternetOpenUrl.
InternetQueryDataAvailable Mengambil jumlah data yang tersedia. Memerlukan handel yang dibuat oleh fungsi FtpOpenFile, atau HttpOpenRequest.
InternetQueryOption Mengambil pengaturan opsi Internet.
InternetReadFile Membaca data URL. Memerlukan handel yang dibuat oleh InternetOpenUrl, FtpOpenFile, atau fungsi HttpOpenRequest.
InternetSetFilePointer Mengatur posisi untuk bacaan berikutnya dalam file. Memerlukan handel yang dibuat olehInternetOpenUrl(hanya pada URL HTTP) atau handel yang dibuat oleh HttpOpenRequest menggunakan kata kerja GET HTTP.
InternetSetOption Mengatur opsi Internet.
InternetSetStatusCallback Mengatur fungsi panggilan balik yang menerima informasi status. Menetapkan fungsi panggilan balik ke handelHINTERNETyang ditunjuk dan semua handel yang berasal darinya.
InternetUnlockRequestFile Membuka kunci file yang dikunci menggunakan fungsiInternetLockRequestFile.

 

Membaca file, menemukan file berikutnya, memanipulasi opsi, dan menyiapkan operasi asinkron umum untuk fungsi yang mendukung berbagai protokol dan HINTERNET menangani jenis.

Membaca File

FungsiInternetReadFiledigunakan untuk mengunduh sumber daya dari handelHINTERNETyang dikembalikan oleh fungsi InternetOpenUrl, FtpOpenFile, atau HttpOpenRequest.

InternetReadFile menerima variabel pointer kosong yang berisi alamat buffer dan pointer ke variabel yang berisi panjang buffer. Fungsi mengembalikan data dalam buffer dan jumlah data yang diunduh ke buffer.

Fungsi WinINet menyediakan dua teknik untuk mengunduh seluruh sumber daya:

InternetQueryDataAvailable mengambil handelHINTERNETyang dibuat oleh InternetOpenUrl, FtpOpenFi, atau HttpOpenRequest (setelah httpSendRequest dipanggil pada handel) dan mengembalikan jumlah byte yang tersedia. Aplikasi harus mengalokasikan buffer yang sama dengan jumlah byte yang tersedia, ditambah 1 untuk karakter null penghentian, dan menggunakan buffer tersebut dengan InternetReadFile. Metode ini tidak selalu berfungsi karena InternetQueryDataAvailable memeriksa ukuran file yang tercantum di header dan bukan file aktual. Informasi dalam file header bisa kedaluarsa, atau file header mungkin hilang, karena saat ini tidak diperlukan di bawah semua standar.

Contoh berikut membaca konten sumber daya yang diakses oleh handel hResource dan ditampilkan dalam kotak edit yang ditunjukkan oleh intCtrlID.

int WINAPI Dumper(HWND hX, int intCtrlID, HINTERNET hResource)
{
    LPTSTR    lpszData;           // buffer for the data
    DWORD     dwSize;             // size of the data available
    DWORD     dwDownloaded;       // size of the downloaded data
    DWORD     dwSizeSum=0;        // size of the data in the text box
    LPTSTR    lpszHolding;        // buffer to merge the text box 
                                  // data and buffer

    // Set the cursor to an hourglass.
    SetCursor(LoadCursor(NULL,IDC_WAIT));

    // This loop handles reading the data.  
    do
    {
        // The call to InternetQueryDataAvailable determines the
        // amount of data available to download.
        if (!InternetQueryDataAvailable(hResource,&dwSize,0,0))
        {
            ErrorOut(hX,GetLastError(),TEXT("InternetReadFile"));
            SetCursor(LoadCursor(NULL,IDC_ARROW));
            return FALSE;
        }
        else
        {    
            // Allocate a buffer of the size returned by
            // InternetQueryDataAvailable.
            lpszData = new TCHAR[dwSize+1];

            // Read the data from the HINTERNET handle.
            if(!InternetReadFile(hResource,(LPVOID)lpszData,
                                 dwSize,&dwDownloaded))
            {
                ErrorOut(hX,GetLastError(),TEXT("InternetReadFile"));
                delete[] lpszData;
                break;
            }
            else
            {
                // Add a null terminator to the end of the 
                // data buffer.
                lpszData[dwDownloaded]='\0';

                // Allocate the holding buffer.
                lpszHolding = new TCHAR[dwSizeSum + dwDownloaded + 1];
                    
                // Check if there has been any data written to 
                // the text box.
                if (dwSizeSum != 0)
                {
                    // Retrieve the data stored in the text 
                    // box, if any.
                    GetDlgItemText(hX,intCtrlID,
                                   (LPTSTR)lpszHolding, 
                                   dwSizeSum);
                         
                    // Add a null terminator at the end of 
                    // the text box data.
                    lpszHolding[dwSizeSum]='\0';
                }
                else
                {
                    // Make the holding buffer an empty string. 
                    lpszHolding[0]='\0';
                }

                size_t cchDest = dwSizeSum + dwDownloaded + 
                                 dwDownloaded + 1;
                LPTSTR pszDestEnd;
                size_t cchRemaining;

                // Add the new data to the holding buffer.
                HRESULT hr = StringCchCatEx(lpszHolding, cchDest, 
                                            lpszData, &pszDestEnd, 
                                            &cchRemaining, 
                                            STRSAFE_NO_TRUNCATION);
                if(SUCCEEDED(hr))
                {
                    // Write the holding buffer to the text box.
                    SetDlgItemText(hX,intCtrlID,(LPTSTR)lpszHolding);

                    // Delete the two buffers.
                    delete[] lpszHolding;
                    delete[] lpszData;

                    // Add the size of the downloaded data to 
                    // the text box data size.
                    dwSizeSum = dwSizeSum + dwDownloaded + 1;

                    // Check the size of the remaining data.  
                    // If it is zero, break.
                    if (dwDownloaded == 0)
                    {
                        break;
                    }                    
                    else
                    {
                        //  Insert error handling code here.
                    }
                }
            }
        }
    }
    while(TRUE);

    // Close the HINTERNET handle.
    InternetCloseHandle(hResource);

    // Set the cursor back to an arrow.
    SetCursor(LoadCursor(NULL,IDC_ARROW));

    // Return.
    return TRUE;
}

InternetReadFile mengembalikan nol byte yang dibaca dan berhasil diselesaikan ketika semua data yang tersedia telah dibaca. Ini memungkinkan aplikasi untuk menggunakanInternetReadFiledalam perulangan untuk mengunduh data dan keluar ketika mengembalikan nol byte yang berhasil dibaca dan diselesaikan.

Contoh berikut membaca sumber daya dari Internet dan menampilkan sumber daya dalam kotak edit yang ditunjukkan oleh intCtrlID. HandelHINTERNET, hInternet, dikembalikan oleh InternetOpenUrl, FtpOpenFile, atau HttpOpenRequest (setelah dikirim oleh HttpSendRequest).

int WINAPI Dump(HWND hX, int intCtrlID, HINTERNET hResource)
{
     DWORD dwSize = 0;
     LPTSTR lpszData;
     LPTSTR lpszOutPut;
     LPTSTR lpszHolding = TEXT("");
     int nCounter = 1;
     int nBufferSize = 0;
     DWORD BigSize = 8000;

     // Set the cursor to an hourglass.
     SetCursor(LoadCursor(NULL,IDC_WAIT));

     // Begin the loop that reads the data.
     do
     {
          // Allocate the buffer.
          lpszData =new TCHAR[BigSize+1];

          // Read the data.
          if(!InternetReadFile(hResource,
                              (LPVOID)lpszData,
                              BigSize,&dwSize))
          {
               ErrorOut(hX,GetLastError(),TEXT("InternetReadFile"));
               delete []lpszData;
               break;
          }
          else
          {
               // Add a null terminator to the end of the buffer.
               lpszData[dwSize]='\0';

               // Check if all of the data has been read.  This should
               // never get called on the first time through the loop.
               if (dwSize == 0)
               {
                    // Write the final data to the text box.
                    SetDlgItemText(hX,intCtrlID,lpszHolding);

                    // Delete the existing buffers.
                    delete [] lpszData;
                    delete [] lpszHolding;
                    break;
               }

               // Determine the buffer size to hold the new data and
               // the data already written to the text box (if any).
               nBufferSize = (nCounter*BigSize)+1;

               // Increment the number of buffers read.
               nCounter++;               

               // Allocate the output buffer.
               lpszOutPut = new TCHAR[nBufferSize];

               // Make sure the buffer is not the initial buffer.
               if(nBufferSize != int(BigSize+1))
               {
                    // Copy the data in the holding buffer.
                    StringCchCopy(lpszOutPut,nBufferSize,lpszHolding);
                    // Add error handling code here.

                    // Concatenate the new buffer with the 
                    // output buffer.
                    StringCchCat(lpszOutPut, nBufferSize, lpszData);
                    // Add error handling code here.
     
                    // Delete the holding buffer.
                    delete [] lpszHolding;
               }
               else
               {
                    // Copy the data buffer.
                    StringCchCopy(lpszOutPut, nBufferSize, lpszData);
                    // Add error handling code here.
               }

               // Allocate a holding buffer.
               lpszHolding = new TCHAR[nBufferSize]; 

               // Copy the output buffer into the holding buffer.
               memcpy(lpszHolding,lpszOutPut,nBufferSize);

               // Delete the other buffers.
               delete [] lpszData;
               delete [] lpszOutPut;

          }

     }
     while (TRUE);

     // Close the HINTERNET handle.
     InternetCloseHandle(hResource);

     // Set the cursor back to an arrow.
     SetCursor(LoadCursor(NULL,IDC_ARROW));

     // Return.
     return TRUE;
}

Menemukan File Berikutnya

FungsiInternetFindNextFiledigunakan untuk menemukan file berikutnya dalam pencarian file, menggunakan parameter pencarian dan handel HINTERNET dari FtpFindFirstFile, atau InternetOpenUrl.

Untuk menyelesaikan pencarian file, terus panggilInternetFindNextFilemenggunakan handelHINTERNETyang dikembalikan oleh FtpFindFirstFile, atau InternetOpenUrl hingga fungsi gagal dengan pesan kesalahan yang diperluas ERROR_NO_MORE_FILES. Untuk mendapatkan informasi kesalahan yang diperluas, panggil fungsiGetLastError.

Contoh berikut menampilkan konten direktori FTP dalam kotak daftar yang ditunjukkan oleh lstDirectory. HandelHINTERNET, hConnect, adalah handel yang dikembalikan oleh fungsiInternetConnect setelah membuat sesi FTP.

bool WINAPI DisplayDir( HWND hX, 
                        int lstDirectory, 
                        HINTERNET hConnect, 
                        DWORD dwFlag )
{
     WIN32_FIND_DATA pDirInfo;
     HINTERNET hDir;
     TCHAR DirList[MAX_PATH];

     // Set the cursor to an hourglass.
     SetCursor(LoadCursor(NULL,IDC_WAIT));

     // Reset the list box.
     SendDlgItemMessage(hX, lstDirectory,LB_RESETCONTENT,0,0);

     // Find the first file.
     hDir = FtpFindFirstFile (hConnect, TEXT ("*.*"), 
                              &pDirInfo, dwFlag, 0);
     if (!hDir)                                     
     {
          // Check if the error was because there were no files.
          if (GetLastError()  == ERROR_NO_MORE_FILES) 
          {
               // Alert user.
               MessageBox(hX, TEXT("There are no files here!!!"), 
                          TEXT("Display Dir"), MB_OK);

               // Close the HINTERNET handle.
               InternetCloseHandle(hDir);

               // Set the cursor back to an arrow.
               SetCursor(LoadCursor(NULL,IDC_ARROW));

               // Return.
               return TRUE;
          }
          else 
          {
               // Call error handler.
               ErrorOut (hX, GetLastError (), TEXT("FindFirst error: "));

               // Close the HINTERNET handle.
               InternetCloseHandle(hDir);

               // Set the cursor back to an arrow.
               SetCursor(LoadCursor(NULL,IDC_ARROW));

               // Return.
               return FALSE;
          }
     }
     else
     {
          // Write the file name to a string.
          StringCchPrintf(DirList, MAX_PATH, pDirInfo.cFileName);

          // Check the type of file.
          if (pDirInfo.dwFileAttributes == FILE_ATTRIBUTE_DIRECTORY)
          {
               // Add <DIR> to indicate that this is 
               // a directory to the user.
               StringCchCat(DirList, MAX_PATH, TEXT(" <DIR> "));
               // Add error handling code here.
          }
       
          // Add the file name (or directory) to the list box.
          SendDlgItemMessage(hX, lstDirectory, LB_ADDSTRING,
                             0, (LPARAM)DirList);
     }
     do
     {
          // Find the next file.
          if (!InternetFindNextFile (hDir, &pDirInfo))
          {
               // Check if there are no more files left. 
               if ( GetLastError() == ERROR_NO_MORE_FILES ) 
               {
                    // Close the HINTERNET handle.
                    InternetCloseHandle(hDir);

                    // Set the cursor back to an arrow.
                    SetCursor(LoadCursor(NULL,IDC_ARROW));

                    // Return.
                    return TRUE;
               }
               else
               {   
                    // Handle the error.
                    ErrorOut (hX, GetLastError(), 
                              TEXT("InternetFindNextFile"));

                    // Close the HINTERNET handle.
                    InternetCloseHandle(hDir);

                    // Set the cursor back to an arrow.
                    SetCursor(LoadCursor(NULL,IDC_ARROW));

                    // Return.
                    return FALSE;
               }
           }
           else
           {
               // Write the file name to a string.
               StringCchPrintf(DirList, MAX_PATH, pDirInfo.cFileName);

               // Check the type of file.
               if(pDirInfo.dwFileAttributes==FILE_ATTRIBUTE_DIRECTORY)
               {
                    // Add <DIR> to indicate that this is a 
                    // directory to the user.
                    StringCchCat(DirList, MAX_PATH, TEXT(" <DIR> "));
                    // Add error handling code here.
               }
     
               // Add the file name (or directory) to the list box.
               SendDlgItemMessage(hX, lstDirectory, LB_ADDSTRING,
                                  0, (LPARAM)DirList);
           }
     }
     while ( TRUE);
     
}

Memanipulasi Opsi

InternetSetOption danInternetQueryOptiondigunakan untuk memanipulasi opsi WinINet.

InternetSetOption menerima variabel yang menunjukkan opsi untuk diatur, buffer untuk menahan pengaturan opsi, dan pointer yang berisi alamat variabel yang berisi panjang buffer.

InternetQueryOption menerima variabel yang menunjukkan opsi untuk mengambil, buffer untuk menahan pengaturan opsi, dan penunjuk yang berisi alamat variabel yang berisi panjang buffer.

Menyiapkan Operasi Asinkron

Secara default, fungsi WinINet beroperasi secara sinkron. Aplikasi dapat meminta operasi asinkron dengan mengatur bendera INTERNET_FLAG_ASYNC dalam panggilan ke fungsi InternetBuka. Semua panggilan di masa mendatang yang dilakukan terhadap handel yang berasal dari handel yang dikembalikan dari InternetBuka dilakukan secara asinkron.

Alasan untuk operasi asinkron versus sinkron adalah untuk memungkinkan aplikasi utas tunggal memaksimalkan pemanfaatan CPU tanpa harus menunggu I/O jaringan selesai. Oleh karena itu, tergantung pada permintaan, operasi mungkin selesai secara sinkron atau asinkron. Aplikasi harus memeriksa kode pengembalian. Jika fungsi mengembalikan FALSE atau NULL, dan GetLastError mengembalikan ERROR_IO_PENDING, permintaan telah dibuat secara asinkron, dan aplikasi dipanggil kembali dengan INTERNET_STATUS_REQUEST_COMPLETE ketika fungsi telah selesai.

Untuk memulai operasi asinkron, aplikasi harus mengatur bendera INTERNET_FLAG_ASYNC dalam panggilannya ke InternetBuka. Aplikasi kemudian harus mendaftarkan fungsi panggilan balik yang valid, menggunakan InternetSetStatusCallback.

Setelah fungsi panggilan balik didaftarkan untuk handel, semua operasi pada handel tersebut dapat menghasilkan indikasi status, asalkan nilai konteks yang disediakan ketika handel dibuat bukan nol. Memberikan nilai konteks nol memaksa operasi untuk diselesaikan secara sinkron, meskipun INTERNET_FLAG_ASYNC ditentukan dalam InternetBuka.

Indikasi status memberikan umpan balik aplikasi tentang kemajuan operasi jaringan, seperti menyelesaikan nama host, menyambungkan ke server, dan menerima data. Tiga indikasi status tujuan khusus dapat dibuat untuk handel:

  • INTERNET_STATUS_HANDLE_CLOSING adalah indikasi status terakhir yang dibuat untuk handel.
  • INTERNET_STATUS_HANDLE_CREATED menunjukkan kapan handel awalnya dibuat.
  • INTERNET_STATUS_REQUEST_COMPLETE menunjukkan operasi asinkron telah selesai.

Aplikasi harus memeriksa struktur INTERNET_ASYNC_RESULT untuk menentukan apakah operasi berhasil atau gagal setelah menerima indikasi INTERNET_STATUS_REQUEST_COMPLETE.

Contoh berikut menunjukkan contoh fungsi panggilan balik dan panggilan ke InternetSetStatusCallback untuk mendaftarkan fungsi sebagai fungsi panggilan balik.

void CALLBACK InternetCallback(
    HINTERNET hInternet,
    DWORD_PTR dwcontext,
    DWORD dwInternetStatus,
    LPVOID lpvStatusInformation,
    DWORD dwStatusInformationLength
    )
{
    _tprintf(TEXT("%0xd %0xp %0xd %0xp %0xd\n"),
             hInternet,
             dwcontext,
             dwInternetStatus,
             lpvStatusInformation,
             dwStatusInformationLength);
};

INTERNET_STATUS_CALLBACK dwISC =
    InternetSetStatusCallback(hInternet, InternetCallback); 

Menutup Handel HINTERNET

Semua handelHINTERNETdapat ditutup dengan menggunakan fungsiInternetCloseHandle. Aplikasi klien harus menutup semua handel HINTERNET yang berasal dari handel HINTERNET yang coba mereka tutup sebelum memanggil InternetCloseHandle pada handel.

Contoh berikut mengilustrasikan hierarki handel.

HINTERNET hRootHandle, hOpenUrlHandle;

hRootHandle = InternetOpen( TEXT("Example"), 
                            INTERNET_OPEN_TYPE_DIRECT, 
                            NULL, 
                            NULL, 0);

hOpenUrlHandle = InternetOpenUrl(hRootHandle, 
    TEXT("https://www.server.com/default.htm"), NULL, 0, 
    INTERNET_FLAG_RAW_DATA,0);

// Close the handle created by InternetOpenUrl so that the
// InternetOpen handle can be closed.
InternetCloseHandle(hOpenUrlHandle); 

// Close the handle created by InternetOpen.
InternetCloseHandle(hRootHandle);

Mengunci dan Membuka Kunci Sumber Daya

FungsiInternetLockRequestFile memungkinkan aplikasi untuk memastikan bahwa sumber daya cache yang terkait dengan handelHINTERNETditeruskan ke cache tidak hilang dari cache. Jika unduhan lain mencoba menerapkan sumber daya yang memiliki URL yang sama dengan file terkunci, cache menghindari penghapusan file dengan melakukan penghapusan yang aman. Setelah aplikasi memanggil fungsiInternetUnlockRequestFile, cache diberikan izin untuk menghapus file.

Jika bendera INTERNET_FLAG_NO_CACHE_WRITE atau INTERNET_FLAG_DONT_CACHE telah diatur, InternetLockRequestFile membuat file sementara dengan ekstensi TMP, kecuali handel tersambung ke sumber daya https. Jika fungsi mengakses sumber daya https dan INTERNET_FLAG_NO_CACHE_WRITE (atau INTERNET_FLAG_DONT_CACHE) telah diatur, InternetLockRequestFile gagal.

Nota

WinINet tidak mendukung implementasi server. Selain itu, tidak boleh digunakan dari layanan. Untuk implementasi atau layanan server, gunakan Microsoft Windows HTTP Services (WinHTTP).