다음을 통해 공유


Common Functions(Windows Internet)

다른 인터넷 프로토콜(예: ftp 및 http)은 동일한 WinINet 함수 중 몇 가지를 사용하여 인터넷에서 정보를 처리합니다. 이러한 일반적인 함수는 적용되는 특정 프로토콜에 관계없이 일관된 방식으로 작업을 처리합니다. 애플리케이션은 이러한 함수를 사용하여 다양한 프로토콜(예: ftp 및 http용 파일 읽기)에서 작업을 처리하는 범용 함수를 만들 수 있습니다.

일반적인 함수는 다음 작업을 처리합니다.

Common Functions 사용

다음 표에서는 WinINet 함수에 포함된 일반적인 함수를 나열합니다. 공통 함수는 다양한 유형의 HINTERNET 핸들에서 사용하거나 다양한 유형의 세션에서 사용할 수 있습니다.

기능 묘사
InternetFindNextFile 파일 열거 또는 검색을 계속합니다. FtpFindFirstFile또는 InternetOpenUrl 함수에서 만든 핸들이 필요합니다.
InternetLockRequestFile 사용자가 사용 중인 파일에 잠금을 배치할 수 있습니다. 이 함수에는 FtpOpenFile, HttpOpenRequest또는 InternetOpenUrl 함수에서 반환된 핸들이 필요합니다.
InternetQueryDataAvailable 사용 가능한 데이터의 양을 검색합니다. FtpOpenFile또는 HttpOpenRequest 함수에서 만든 핸들이 필요합니다.
InternetQueryOption 인터넷 옵션의 설정을 검색합니다.
InternetReadFile URL 데이터를 읽습니다. InternetOpenUrl, FtpOpenFile또는 HttpOpenRequest 함수에서 만든 핸들이 필요합니다.
InternetSetFilePointer 파일에서 다음 읽기의 위치를 설정합니다. internetOpenUrl만든 핸들(HTTP URL에만 해당) 또는 GET HTTP 동사를 사용하여 HttpOpenRequest 만든 핸들이 필요합니다.
InternetSetOption 인터넷 옵션을 설정합니다.
InternetSetStatusCallback 상태 정보를 수신하는 콜백 함수를 설정합니다. 지정된 HINTERNET 핸들 및 해당 핸들에서 파생된 모든 핸들에 콜백 함수를 할당합니다.
InternetUnlockRequestFile InternetLockRequestFile 함수를 사용하여 잠긴 파일의 잠금을 해제합니다.

 

파일 읽기, 다음 파일 찾기, 옵션 조작 및 비동기 작업 설정은 다양한 프로토콜을 지원하는 함수와 HINTERNET 핸들 형식에 공통적입니다.

파일 읽기

InternetReadFile 함수는 InternetOpenUrl, FtpOpenFile또는 HttpOpenRequest 함수에서 반환된 HINTERNET 핸들에서 리소스를 다운로드하는 데 사용됩니다.

InternetReadFile 버퍼의 주소와 버퍼 길이가 포함된 변수에 대한 포인터를 포함하는 void 포인터 변수를 허용합니다. 함수는 버퍼의 데이터와 버퍼에 다운로드된 데이터의 양을 반환합니다.

WinINet 함수는 전체 리소스를 다운로드하는 두 가지 기술을 제공합니다.

InternetQueryDataAvailableInternetOpenUrl, FtpOpenFile또는 HttpOpenRequest(핸들에서 HttpSendRequest 호출된 후)에서 만든 HINTERNET 핸들을 사용하고 사용 가능한 바이트 수를 반환합니다. 애플리케이션은 사용 가능한 바이트 수와 동일한 버퍼를 할당하고 종료 null 문자에 대해 1을 할당하고 InternetReadFile해당 버퍼를 사용해야 합니다. InternetQueryDataAvailable실제 파일이 아닌 헤더에 나열된 파일 크기를 확인하므로 이 메서드가 항상 작동하지는 않습니다. 헤더 파일의 정보가 오래되었거나 헤더 파일이 누락될 수 있습니다( 현재 모든 표준에 따라 필요하지 않기 때문에).

다음 예제에서는 hResource 핸들에서 액세스하고 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 0바이트 읽기를 반환하고 사용 가능한 모든 데이터를 읽었을 때 성공적으로 완료됩니다. 이렇게 하면 애플리케이션이 루프에서 InternetReadFile 사용하여 데이터를 다운로드하고 0바이트를 읽고 성공적으로 완료할 때 종료할 수 있습니다.

다음 예제에서는 인터넷에서 리소스를 읽고 intCtrlID로 표시된 편집 상자에 리소스를 표시합니다. HINTERNET 핸들 hInternet은 InternetOpenUrl, FtpOpenFile또는 HttpOpenRequest(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;
}

다음 파일 찾기

InternetFindNextFile 함수는 FtpFindFirstFile또는 internetOpenUrl검색 매개 변수 및 HINTERNET 핸들을 사용하여 파일 검색에서 다음 파일을 찾는 데 사용됩니다.

파일 검색을 완료하려면 FtpFindFirstFile반환된 HINTERNET 핸들을 사용하여 InternetFindNextFile 호출하거나 확장 오류 메시지 ERROR_NO_MORE_FILES함수가 실패할 때까지 InternetOpenUrl. 확장 오류 정보를 얻으려면 GetLastError 함수를 호출합니다.

다음 예제에서는 lstDirectory로 표시된 목록 상자에 FTP 디렉터리의 내용을 표시합니다. HINTERNET 핸들 hConnect는 FTP 세션을 설정한 후 InternetConnect 함수에서 반환하는 핸들입니다.

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

옵션 조작

InternetSetOptionInternetQueryOption 사용하여 WinINet 옵션을 조작합니다.

InternetSetOption 설정할 옵션, 옵션 설정을 저장할 버퍼 및 버퍼 길이가 포함된 변수의 주소를 포함하는 포인터를 나타내는 변수를 허용합니다.

InternetQueryOption 검색 옵션을 나타내는 변수, 옵션 설정을 저장할 버퍼 및 버퍼 길이가 포함된 변수의 주소를 포함하는 포인터를 허용합니다.

비동기 작업 설정

기본적으로 WinINet 함수는 동기적으로 작동합니다. 애플리케이션은 InternetOpen 함수 호출에서 INTERNET_FLAG_ASYNC 플래그를 설정하여 비동기 작업을 요청할 수 있습니다. InternetOpen 반환된 핸들에서 파생된 핸들에 대해 만들어진 모든 이후 호출은 비동기적으로 이루어집니다.

비동기 및 동기 작업의 근거는 단일 스레드 애플리케이션이 네트워크 I/O가 완료될 때까지 기다리지 않고도 CPU 사용률을 최대화할 수 있도록 하는 것입니다. 따라서 요청에 따라 작업이 동기적으로 또는 비동기적으로 완료될 수 있습니다. 애플리케이션은 반환 코드를 확인해야 합니다. 함수가 FALSE 또는 NULL반환하고 GetLastErrorERROR_IO_PENDING 반환하는 경우 요청이 비동기적으로 수행되고 함수가 완료되면 INTERNET_STATUS_REQUEST_COMPLETE 애플리케이션이 다시 호출됩니다.

비동기 작업을 시작하려면 애플리케이션이 internetOpen호출에서 INTERNET_FLAG_ASYNC 플래그를 설정해야 합니다. 그런 다음 애플리케이션은 InternetSetStatusCallback사용하여 유효한 콜백 함수를 등록해야 합니다.

핸들에 대해 콜백 함수가 등록되면 핸들을 만들 때 제공된 컨텍스트 값이 0이 아닌 경우 해당 핸들의 모든 작업이 상태 표시를 생성할 수 있습니다. 컨텍스트 값이 0이면 internetOpenINTERNET_FLAG_ASYNC 지정되었더라도 작업이 동기적으로 완료됩니다.

상태 표시는 호스트 이름 확인, 서버에 연결 및 데이터 수신과 같은 네트워크 작업의 진행 상황에 대한 애플리케이션 피드백을 제공합니다. 핸들에 대해 다음과 같은 세 가지 특수 목적 상태 표시를 수행할 수 있습니다.

  • INTERNET_STATUS_HANDLE_CLOSING 핸들에 대해 만들어진 마지막 상태 표시입니다.
  • INTERNET_STATUS_HANDLE_CREATED 핸들이 처음 만들어지는 시기를 나타냅니다.
  • INTERNET_STATUS_REQUEST_COMPLETE 비동기 작업이 완료되었음을 나타냅니다.

애플리케이션은 INTERNET_STATUS_REQUEST_COMPLETE 표시를 받은 후 작업이 성공했는지 또는 실패했는지 여부를 확인하기 위해 INTERNET_ASYNC_RESULT 구조를 확인해야 합니다.

다음 샘플에서는 콜백 함수의 예와 함수를 콜백 함수로 등록하기 위해 InternetSetStatusCallback 호출하는 방법을 보여 줍니다.

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

HINTERNET 핸들 닫기

InternetCloseHandle 함수를 사용하여 모든 HINTERNET 핸들을 닫을 수 있습니다. 클라이언트 애플리케이션은 핸들에서 InternetCloseHandle 호출하기 전에 닫으려는 HINTERNET 핸들에서 파생된 모든 HINTERNET 핸들을 닫아야 합니다.

다음 예제에서는 핸들 계층 구조를 보여 줍니다.

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

리소스 잠금 및 잠금 해제

InternetLockRequestFile 함수를 사용하면 애플리케이션에서 전달된 HINTERNET 핸들과 연결된 캐시된 리소스가 캐시에서 사라지지 않도록 할 수 있습니다. 다른 다운로드에서 잠긴 파일과 URL이 동일한 리소스를 커밋하려고 하면 캐시에서 안전한 삭제를 수행하여 파일을 제거하지 않습니다. 애플리케이션이 InternetUnlockRequestFile 함수를 호출하면 캐시에 파일을 삭제할 수 있는 권한이 부여됩니다.

INTERNET_FLAG_NO_CACHE_WRITE 또는 INTERNET_FLAG_DONT_CACHE 플래그가 설정된 경우 InternetLockRequestFile 핸들이 https 리소스에 연결되지 않는 한 확장명 TMP를 사용하여 임시 파일을 만듭니다. 함수가 https 리소스에 액세스하고 INTERNET_FLAG_NO_CACHE_WRITE(또는 INTERNET_FLAG_DONT_CACHE)가 설정된 경우 InternetLockRequestFile실패합니다.

메모

WinINet은 서버 구현을 지원하지 않습니다. 또한 서비스에서 사용하면 안 됩니다. 서버 구현 또는 서비스의 경우 WinHTTP(Microsoft Windows HTTP 서비스) 사용합니다.