Dela via


Common Functions (Windows Internet)

De olika Internetprotokollen (till exempel ftp och http) använder flera av samma WinINet-funktioner för att hantera information på Internet. Dessa vanliga funktioner hanterar sina uppgifter på ett konsekvent sätt, oavsett vilket protokoll de tillämpas på. Program kan använda dessa funktioner för att skapa allmänna funktioner som hanterar uppgifter i de olika protokollen (till exempel att läsa filer för ftp och http).

De vanliga funktionerna hanterar följande uppgifter:

Använda Vanliga funktioner

I följande tabell visas de vanliga funktioner som ingår i WinINet-funktionerna. De vanliga funktionerna kan användas på olika typer av HINTERNET- referenser eller kan användas under olika typer av sessioner.

Funktion Beskrivning
InternetFindNextFile Fortsätter filuppräkning eller sökning. Kräver ett handtag som skapats av funktionen FtpFindFirstFileeller InternetOpenUrl.
InternetLockRequestFile Tillåter att användaren placerar ett lås på filen som används. Den här funktionen kräver en referens som returneras av funktionen FtpOpenFile, HttpOpenRequesteller InternetOpenUrl.
InternetQueryDataAvailable Hämtar mängden tillgängliga data. Kräver ett handtag som skapats av funktionen FtpOpenFileeller HttpOpenRequest.
InternetQueryOption Hämtar inställningen för ett Internet-alternativ.
InternetReadFile Läser URL-data. Kräver ett handtag som skapats av funktionen InternetOpenUrl, FtpOpenFileeller HttpOpenRequest.
InternetSetFilePointer Anger positionen för nästa läsning i en fil. Kräver ett handtag som skapats av InternetOpenUrl (endast på en HTTP-URL) eller ett handtag som skapats av HttpOpenRequest med hjälp av GET HTTP-verbet.
InternetSetOption Anger ett Internetalternativ.
InternetSetStatusCallback Anger en återanropsfunktion som tar emot statusinformation. Tilldelar en återanropsfunktion till den avsedda HINTERNET- handtag och alla referenser som härletts från den.
InternetUnlockRequestFile Låser upp en fil som låstes med hjälp av funktionen InternetLockRequestFile.

 

Att läsa filer, hitta nästa fil, ändra alternativ och konfigurera asynkrona åtgärder är vanligt för de funktioner som stöder olika protokoll och HINTERNET- hanterar typer.

Läsa filer

Funktionen InternetReadFile används för att ladda ned resurser från en HINTERNET--referens som returneras av funktionen InternetOpenUrl, FtpOpenFileeller HttpOpenRequest.

InternetReadFile accepterar en tomrumspekarvariabel som innehåller adressen till en buffert och en pekare till en variabel som innehåller buffertens längd. Funktionen returnerar data i bufferten och mängden data som laddas ned till bufferten.

WinINet-funktionerna innehåller två tekniker för att ladda ned en hel resurs:

InternetQueryDataAvailable tar HINTERNET handtag som skapats av InternetOpenUrl, FtpOpenFile, eller HttpOpenRequest (efter HttpSendRequest har anropats på handtaget) och returnerar antalet tillgängliga byte. Programmet ska allokera en buffert som är lika med antalet tillgängliga byte plus 1 för det avslutande null--tecknet och använda bufferten med InternetReadFile. Den här metoden fungerar inte alltid eftersom InternetQueryDataAvailable kontrollerar filstorleken som anges i rubriken och inte den faktiska filen. Informationen i huvudfilen kan vara inaktuell, eller så kan huvudfilen saknas, eftersom den för närvarande inte krävs enligt alla standarder.

I följande exempel läss innehållet i resursen som används av hResource-handtaget och visas i redigeringsrutan som anges av 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 returnerar noll byte läsning och slutförs när alla tillgängliga data har lästs. Detta gör att ett program kan använda InternetReadFile i en loop för att ladda ned data och avsluta när det returnerar noll byte läsning och slutförs korrekt.

I följande exempel läss resursen från Internet och resursen visas i redigeringsrutan som anges av intCtrlID. Handtaget HINTERNET, hInternet, returnerades av InternetOpenUrl, FtpOpenFileeller HttpOpenRequest (efter att ha skickats av 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;
}

Hitta nästa fil

Funktionen InternetFindNextFile används för att hitta nästa fil i en filsökning med hjälp av sökparametrarna och HINTERNET- hantera från FtpFindFirstFileeller InternetOpenUrl.

Om du vill slutföra en filsökning fortsätter du att anropa InternetFindNextFile med hjälp av HINTERNET--handtag som returneras av FtpFindFirstFileeller InternetOpenUrl tills funktionen misslyckas med det utökade felmeddelandet ERROR_NO_MORE_FILES. Om du vill hämta den utökade felinformationen anropar du funktionen GetLastError.

I följande exempel visas innehållet i en FTP-katalog i listrutan som anges av lstDirectory. HINTERNET--handtaget hConnect är en referens som returneras av funktionen InternetConnect när en FTP-session har upprättats.

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);
     
}

Ändra alternativ

InternetSetOption och InternetQueryOption används för att ändra WinINet-alternativen.

InternetSetOption accepterar en variabel som anger alternativet att ange, en buffert som innehåller alternativinställningen och en pekare som innehåller adressen till variabeln som innehåller buffertens längd.

InternetQueryOption accepterar en variabel som anger alternativet att hämta, en buffert som innehåller alternativinställningen och en pekare som innehåller adressen till variabeln som innehåller buffertens längd.

Konfigurera asynkrona åtgärder

Som standard fungerar WinINet-funktionerna synkront. Ett program kan begära asynkron åtgärd genom att ange flaggan INTERNET_FLAG_ASYNC i anropet till funktionen InternetOpen. Alla framtida anrop mot referenser som härleds från handtaget som returneras från InternetÖppna görs asynkront.

Syftet med asynkron kontra synkron åtgärd är att tillåta att ett entrådat program maximerar användningen av processorn utan att behöva vänta tills nätverks-I/O har slutförts. Beroende på begäran kan åtgärden därför slutföras synkront eller asynkront. Programmet bör kontrollera returkoden. Om en funktion returnerar FALSE eller NULLoch GetLastError returnerar ERROR_IO_PENDING, har begäran gjorts asynkront och programmet anropas tillbaka med INTERNET_STATUS_REQUEST_COMPLETE när funktionen har slutförts.

Om du vill påbörja asynkron åtgärd måste programmet ange flaggan INTERNET_FLAG_ASYNC i anropet till InternetOpen. Programmet måste sedan registrera en giltig återanropsfunktion med hjälp av InternetSetStatusCallback.

När en återanropsfunktion har registrerats för en referens kan alla åtgärder på handtaget generera statusinformation, förutsatt att det kontextvärde som angavs när handtaget skapades inte var noll. Om du anger ett nollkontextvärde måste en åtgärd slutföras synkront, även om INTERNET_FLAG_ASYNC angavs i InternetOpen.

Statusinformation ger programmet feedback om förloppet för nätverksåtgärder, till exempel att matcha ett värdnamn, ansluta till en server och ta emot data. Tre särskilda statusbeteckningar kan göras för ett handtag:

  • INTERNET_STATUS_HANDLE_CLOSING är den sista statusindikatorn som görs för ett handtag.
  • INTERNET_STATUS_HANDLE_CREATED anger när handtaget skapas.
  • INTERNET_STATUS_REQUEST_COMPLETE anger att en asynkron åtgärd har slutförts.

Programmet måste kontrollera INTERNET_ASYNC_RESULT struktur för att avgöra om åtgärden lyckades eller misslyckades efter att ha fått en INTERNET_STATUS_REQUEST_COMPLETE indikation.

Följande exempel visar ett exempel på en återanropsfunktion och ett anrop till InternetSetStatusCallback för att registrera funktionen som återanropsfunktion.

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); 

Stänga HINTERNET-handtag

Alla HINTERNET- referenser kan stängas med hjälp av funktionen InternetCloseHandle. Klientprogram måste stänga alla HINTERNET- referenser som härleds från HINTERNET hanterar de försöker stänga innan de anropar InternetCloseHandle på handtaget.

I följande exempel visas referenshierarkin.

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);

Låsa och låsa upp resurser

Med funktionen InternetLockRequestFile kan ett program se till att den cachelagrade resurs som är associerad med HINTERNET- referens som skickas till den inte försvinner från cacheminnet. Om en annan nedladdning försöker checka in en resurs som har samma URL som den låsta filen undviker cacheminnet att ta bort filen genom att göra en säker borttagning. När programmet anropar funktionen InternetUnlockRequestFile får cachen behörighet att ta bort filen.

Om flaggan INTERNET_FLAG_NO_CACHE_WRITE eller INTERNET_FLAG_DONT_CACHE har angetts skapar InternetLockRequestFile en temporär fil med tillägget TMP, såvida inte handtaget är anslutet till en https-resurs. Om funktionen har åtkomst till en https-resurs och INTERNET_FLAG_NO_CACHE_WRITE (eller INTERNET_FLAG_DONT_CACHE) har angetts misslyckas InternetLockRequestFile.

Not

WinINet stöder inte serverimplementeringar. Dessutom bör den inte användas från en tjänst. För serverimplementeringar eller tjänster använder du Microsoft Windows HTTP Services (WinHTTP).