關於WININET的異步使用的代碼和一些相關知識

全部轉自 http://loskill.icode.csdn.net/post/2007/05/31/53930,如下代碼所示

 

在WinInet中使用異步方式

loskill @ 2007-05-31 17:19 | C++

WinInet的異步調用
 #include<WINDOWS.H>  
#include<WININET.H>  
#include<IOSTREAM.H>  
 
HANDLE hConnectedEvent, hRequestOpenedEvent, hRequestCompleteEvent;  
HINTERNET hInstance, hConnect, hRequest;  
char *lpszUrl, *lpszServer;  
 
BOOL bAllDone = FALSE;  
BOOL bVerbose = FALSE;  
 
void __stdcall Callback(HINTERNET hInternet,  
              DWORD dwContext,  
              DWORD dwInternetStatus,  
              LPVOID lpStatusInfo,  
              DWORD dwStatusInfoLen);  
 
void main(int argc, char *argv[])  
{  
    if (argc != 3)  
    {  
        if ((argc == 4) && (argv[3][0] == 'v'))  
            bVerbose = TRUE;  
        else 
        {  
            cout << "Usage: asynchttp <SERVER> <URL> [v]" << endl;  
            cout << "   <SERVER> is the hostname of the http server" << endl;  
            cout << "   <URL> is the url of the object you are requesting (without the hostname)" << endl;  
            cout << "   'v' for verbose output" << endl << endl;  
            cout << "   Example: asynchttp www.domain.com /docs/readme.htm v" << endl;  
            return;  
        }  
    }  
 
    lpszServer = argv[1];  
    lpszUrl = argv[2];  
 
    hConnectedEvent = CreateEvent(NULL, FALSE, FALSE, NULL);  
    hRequestOpenedEvent = CreateEvent(NULL, FALSE, FALSE, NULL);  
    hRequestCompleteEvent = CreateEvent(NULL, FALSE, FALSE, NULL);  
 
    hInstance = InternetOpen("asynchttp",   
                             INTERNET_OPEN_TYPE_PRECONFIG,  
                             NULL,  
                             NULL,  
                             INTERNET_FLAG_ASYNC); // ASYNC Flag  
 
    if (hInstance == NULL)  
    {  
        cout << "InternetOpen failed, error " << GetLastError();  
        return;  
    }  
 
    // Setup callback function  
    if (InternetSetStatusCallback(hInstance,  
                                  (INTERNET_STATUS_CALLBACK)&Callback) == INTERNET_INVALID_STATUS_CALLBACK)  
    {  
        cout << "InternetSetStatusCallback failed, error " << GetLastError();  
        return;  
    }  
 
    // First call that will actually complete asynchronously even  
    // though there is no network traffic  
    hConnect = InternetConnect(hInstance,   
                               lpszServer,   
                               INTERNET_DEFAULT_HTTP_PORT,  
                               NULL,  
                               NULL,  
                               INTERNET_SERVICE_HTTP,  
                               0,  
                               1); // Connection handle's Context  
    if (hConnect == NULL)  
    {  
        if (GetLastError() != ERROR_IO_PENDING)  
        {  
            cout << "InternetConnect failed, error " << GetLastError();  
            return;  
        }  
        // Wait until we get the connection handle  
        WaitForSingleObject(hConnectedEvent, INFINITE);  
    }  
 
 
    // Open the request  
    hRequest = HttpOpenRequest(hConnect,   
                               "GET",   
                               lpszUrl,  
                               NULL,  
                               NULL,  
                               NULL,  
                               INTERNET_FLAG_RELOAD | INTERNET_FLAG_NO_CACHE_WRITE,  
                               2);  // Request handle's context   
    if (hRequest == NULL)  
    {  
        if (GetLastError() != ERROR_IO_PENDING)  
        {  
            cout << "HttpOpenRequest failed, error " << GetLastError();  
            return;  
        }  
        // Wait until we get the request handle  
        WaitForSingleObject(hRequestOpenedEvent, INFINITE);  
    }  
 
    if (!HttpSendRequest(hRequest,   
                         NULL,   
                         0,   
                         NULL,  
                         0))  
    {  
        if (GetLastError() != ERROR_IO_PENDING)  
        {  
            cout << "HttpSendRequest failed, error " << GetLastError();  
            return;  
        }  
    }  
      
    if (bVerbose)  
    {  
        cout << "HttpSendRequest called successfully" << endl;  
        cout.flush();  
    }  
 
    WaitForSingleObject(hRequestCompleteEvent, INFINITE);  
 
    cout << "------------------- Read the response -------------------" << endl;  
    char lpReadBuff[256];  
 
    do 
    {  
        INTERNET_BUFFERS InetBuff;  
        FillMemory(&InetBuff, sizeof(InetBuff), 0);  
        InetBuff.dwStructSize = sizeof(InetBuff);  
        InetBuff.lpvBuffer = lpReadBuff;  
        InetBuff.dwBufferLength = sizeof(lpReadBuff) - 1;  
          
        if (bVerbose)  
        {  
            cout << "Calling InternetReadFileEx" << endl;  
            cout.flush();  
        }  
 
        if (!InternetReadFileEx(hRequest,  
                              &InetBuff,  
                              0, 2))  
        {  
            if (GetLastError() == ERROR_IO_PENDING)  
            {  
                if (bVerbose)  
                {  
                    cout << "Waiting for InternetReadFileEx to complete" << endl;  
                    cout.flush();  
                }  
                WaitForSingleObject(hRequestCompleteEvent, INFINITE);  
            }  
            else 
            {  
                cout << "InternetReadFileEx failed, error " << GetLastError();  
                cout.flush();  
                return;  
            }  
        }  
 
        lpReadBuff[InetBuff.dwBufferLength] = 0;  
        cout << lpReadBuff;  
        cout.flush();  
 
        if (InetBuff.dwBufferLength == 0)   
            bAllDone = TRUE;  
 
    } while (bAllDone == FALSE);  
 
    cout << endl << endl << "------------------- Request Complete ----------------" << endl;  
 
}  
 
void __stdcall Callback(HINTERNET hInternet,  
              DWORD dwContext,  
              DWORD dwInternetStatus,  
              LPVOID lpStatusInfo,  
              DWORD dwStatusInfoLen)  
{  
    if (bVerbose)  
    {  
        cout << "Callback dwInternetStatus: " << dwInternetStatus << " Context: " << dwContext << endl;  
        cout.flush();  
    }  
 
    switch(dwContext)  
    {  
    case 1: // Connection handle  
        if (dwInternetStatus == INTERNET_STATUS_HANDLE_CREATED)  
        {  
            INTERNET_ASYNC_RESULT *pRes = (INTERNET_ASYNC_RESULT *)lpStatusInfo;  
            hConnect = (HINTERNET)pRes->dwResult;  
            if (bVerbose)  
            {  
                cout << "Connect handle created" << endl;  
                cout.flush();  
            }  
            SetEvent(hConnectedEvent);  
        }  
        break;  
    case 2: // Request handle  
        switch(dwInternetStatus)  
        {  
        case INTERNET_STATUS_HANDLE_CREATED:  
            {  
                INTERNET_ASYNC_RESULT *pRes = (INTERNET_ASYNC_RESULT *)lpStatusInfo;  
                hRequest = (HINTERNET)pRes->dwResult;  
                if (bVerbose)  
                {  
                    cout << "Request handle created" << endl;  
                    cout.flush();  
                }  
                SetEvent(hRequestOpenedEvent);  
            }  
            break;  
        case INTERNET_STATUS_REQUEST_SENT:  
            {  
                DWORD *lpBytesSent = (DWORD*)lpStatusInfo;  
                if (bVerbose)  
                {  
                    cout << "Bytes Sent: " << *lpBytesSent << endl;  
                    cout.flush();  
                }  
            }  
            break;  
        case INTERNET_STATUS_REQUEST_COMPLETE:  
            {  
                INTERNET_ASYNC_RESULT *pAsyncRes = (INTERNET_ASYNC_RESULT *)lpStatusInfo;  
                if (bVerbose)  
                {  
                    cout << "Function call finished" << endl;  
                    cout << "dwResult: " << pAsyncRes->dwResult << endl;  
                    cout << "dwError:  " << pAsyncRes->dwError << endl;  
                    cout.flush();  
                }  
                SetEvent(hRequestCompleteEvent);  
            }  
            break;  
        case INTERNET_STATUS_RECEIVING_RESPONSE:  
            if (bVerbose)  
            {  
                cout << "Receiving Response" << endl;  
                cout.flush();  
            }  
            break;  
        case INTERNET_STATUS_RESPONSE_RECEIVED:  
            {  
                DWORD *dwBytesReceived = (DWORD*)lpStatusInfo;  
                if (*dwBytesReceived == 0)  
                    bAllDone = TRUE;  
                if (bVerbose)  
                {  
                    cout << "Received " << *dwBytesReceived << endl;  
                    cout.flush();  
                }  
            }  
 
        }  
 
    }  
 

如何通過創建另一個線程控制連接超時值(轉自MSDN)

loskill @ 2007-05-31 16:53 | C++

 要對設置超值 InternetSetOption API 錯誤由創建另一個線程此 acticle 顯示解決。 有關錯誤, 請參見下列文章 Microsoft 知識庫文章
#include <WINDOWS.H>  
   #include <WININET.H>  
   #include <IOSTREAM.H>  
 
   DWORD WINAPI WorkerFunction( LPVOID );   
   HINTERNET g_hOpen, g_hConnect;  
 
   typedef struct   
   {  
       CHAR* pHost;  
       CHAR* pUser;  
       CHAR* pPass;  
   } PARM;  
 
   void main()  
   {  
       CHAR    szHost[] = "localhost";  
       CHAR    szUser[] = "JoeB";  
       CHAR    szPass[] = "test";  
       CHAR    szLocalFile[] = "localfile";  
       CHAR    szRemoteFile[] = "remotefile";  
       DWORD   dwExitCode;  
       DWORD   dwTimeout;  
       PARM    threadParm;  
 
       g_hOpen = 0;  
       if ( !( g_hOpen = InternetOpen ( "FTP sample",   
                                        LOCAL_INTERNET_ACCESS,   
                                        NULL,   
                                        0,   
                                        0 ) ) )  
       {           
           cerr << "Error on InternetOpen: " << GetLastError() << endl;  
           return ;  
       }  
 
       // Create a worker thread   
       HANDLE   hThread;   
       DWORD    dwThreadID;  
       threadParm.pHost = szHost;  
       threadParm.pUser = szUser;  
       threadParm.pPass = szPass;  
 
       hThread = CreateThread(  
                     NULL,            // Pointer to thread security attributes   
                     0,               // Initial thread stack size, in bytes   
                     WorkerFunction,  // Pointer to thread function   
                     &threadParm,     // The argument for the new thread  
                     0,               // Creation flags   
                     &dwThreadID      // Pointer to returned thread identifier   
                 );      
 
       // Wait for the call to InternetConnect in worker function to complete  
       dwTimeout = 5000; // in milliseconds  
       if ( WaitForSingleObject ( hThread, dwTimeout ) == WAIT_TIMEOUT )  
       {  
           cout << "Can not connect to server in "   
                << dwTimeout << " milliseconds" << endl;  
           if ( g_hOpen )  
   InternetCloseHandle ( g_hOpen );  
           // Wait until the worker thread exits  
           WaitForSingleObject ( hThread, INFINITE );  
           cout << "Thread has exited" << endl;  
           return ;  
       }  
      
       // The state of the specified object (thread) is signaled  
       dwExitCode = 0;  
       if ( !GetExitCodeThread( hThread, &dwExitCode ) )  
       {  
           cerr << "Error on GetExitCodeThread: " << GetLastError() << endl;  
           return ;  
       }  
 
       CloseHandle (hThread);  
       if ( dwExitCode )  
       // Worker function failed  
          return ;  
      
       if ( !FtpGetFile ( g_hConnect,   
                          szRemoteFile,  
                          szLocalFile,  
                          FALSE,INTERNET_FLAG_RELOAD,   
                          FTP_TRANSFER_TYPE_ASCII,  
                          0 ) )  
       {  
           cerr << "Error on FtpGetFile: " << GetLastError() << endl;  
           return ;  
       }  
 
       if ( g_hConnect )  
           InternetCloseHandle( g_hConnect );  
       if ( g_hOpen )  
           InternetCloseHandle( g_hOpen );  
 
       return ;  
   }  
 
   /////////////////// WorkerFunction //////////////////////   
   DWORD WINAPI   
   WorkerFunction(  
       IN LPVOID vThreadParm  
   )  
   /* 
   Purpose: 
       Call InternetConnect to establish a FTP session   
   Arguments: 
       vThreadParm - points to PARM passed to thread 
   Returns: 
       returns 0   
   */   
   {  
       PARM* pThreadParm;  
       // Initialize local pointer to void pointer passed to thread  
       pThreadParm = (PARM*)vThreadParm;  
       g_hConnect = 0;  
      
       if ( !( g_hConnect = InternetConnect (  
                                g_hOpen,   
                                pThreadParm->pHost,  
                                INTERNET_INVALID_PORT_NUMBER,  
                                pThreadParm->pUser,  
pThreadParm->pPass,  
                                INTERNET_SERVICE_FTP,   
                                0,  
                                0 ) ) )  
       {  
           cerr << "Error on InternetConnnect: " << GetLastError() << endl;  
           return 1; // failure  
       }  
         
       return 0;  // success  
   } 
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章