Bagikan melalui


Fungsi Umum (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 oleh fungsi FtpFindFirstFile, atau InternetOpenUrl .
InternetLockRequestFile Memungkinkan pengguna untuk menempatkan kunci pada file yang sedang digunakan. Fungsi ini memerlukan handel yang dikembalikan oleh fungsi FtpOpenFile, HttpOpenRequest, atau 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 fungsi InternetOpenUrl, FtpOpenFile, atau HttpOpenRequest .
InternetSetFilePointer Mengatur posisi untuk bacaan berikutnya dalam file. Memerlukan handel yang dibuat oleh InternetOpenUrl (hanya pada URL HTTP) atau handel yang dibuat oleh HttpOpenRequest menggunakan kata kerja HTTP GET.
InternetSetOption Mengatur opsi Internet.
InternetSetStatusCallback Mengatur fungsi panggilan balik yang menerima informasi status. Menetapkan fungsi panggilan balik ke handel HINTERNET yang ditunjuk dan semua handel yang berasal darinya.
InternetUnlockRequestFile Membuka kunci file yang dikunci menggunakan fungsi InternetLockRequestFile .

 

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

Membaca File

Fungsi InternetReadFile digunakan untuk mengunduh sumber daya dari handel HINTERNET yang 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 dalam buffer.

Fungsi WinINet menyediakan dua teknik untuk mengunduh seluruh sumber daya:

InternetQueryDataAvailable mengambil handel HINTERNET yang dibuat oleh InternetOpenUrl, FtpOpenFile, 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 yang mengakhiri, 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 menggunakan InternetReadFile dalam perulangan untuk mengunduh data dan keluar ketika mengembalikan nol byte yang dibaca dan berhasil diselesaikan.

Contoh berikut membaca sumber daya dari Internet dan menampilkan sumber daya dalam kotak edit yang ditunjukkan oleh intCtrlID. Handel HINTERNET , 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

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

Untuk menyelesaikan pencarian file, terus panggil InternetFindNextFile menggunakan handel HINTERNET yang dikembalikan oleh FtpFindFirstFile, atau InternetOpenUrl hingga fungsi gagal dengan pesan kesalahan yang diperluas ERROR_NO_MORE_FILES. Untuk mendapatkan informasi kesalahan yang diperluas, panggil fungsi GetLastError .

Contoh berikut menampilkan konten direktori FTP dalam kotak daftar yang ditunjukkan oleh lstDirectory. Handel HINTERNET , hConnect, adalah handel yang dikembalikan oleh fungsi InternetConnect 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 dan InternetQueryOption digunakan untuk memanipulasi opsi WinINet.

InternetSetOption menerima variabel yang menunjukkan opsi untuk diatur, buffer untuk menahan pengaturan opsi, dan penunjuk 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 InternetOpen . 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 satu utas 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 selesai secara sinkron, meskipun INTERNET_FLAG_ASYNC ditentukan di InternetOpen.

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 handel HINTERNET dapat ditutup dengan menggunakan fungsi InternetCloseHandle . 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

Fungsi InternetLockRequestFile memungkinkan aplikasi untuk memastikan bahwa sumber daya cache yang terkait dengan handel HINTERNET yang diteruskan ke aplikasi 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 fungsi InternetUnlockRequestFile , cache diberi 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 terhubung 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.

Catatan

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