2011-07-28 131 views
3

我有一些代碼(它實際上是通過Web界面發送SMS消息,但這不相關)。該代碼在代理服務器的缺席中正常工作,但一個客戶想要使用此配置。我一直在使用我們的代理進行測試,但無法正常工作。當通過幫助下苦讀,我發現MSKB文章195650(如何處理代理授權與WinInet的),其中包含的智慧這顆珍珠:MFC + Wininet +代理身份驗證=問題

There are several ways to handle HTTP_STATUS_PROXY_AUTH_REQ without 
displaying a user interface. By far the easiest way to do this is by 
using the InternetSetOption function with the flags 
INTERNET_OPTION_PROXY_PASSWORD and INTERNET_OPTION_PROXY_USERNAME... 

...The same functionality can be accomplished in an MFC application 
by detecting HTTP_STATUS_PROXY_AUTH_REQ, calling 
CHttpConnection::SetOption, then re-calling CHttpFile::SendRequest. 

所以我實現我的這個代碼的解決方案,檢測來自一個407錯誤代理需要身份驗證,然後通過SetOption調用提供基本身份驗證:

 if (AfxParseURL (m_csServerUrl, dwServiceType, csServerName, csObjectName, nPort)) 
    { 
     CString csProxy = m_pOwner->GetProxyServerSetting(); 
     if (csProxy.GetLength() > 0) 
     { 
      pSession = new CMyInternetSession (TEXT("SmGen"), 
               1, 
               INTERNET_OPEN_TYPE_PROXY, 
               csProxy, 
               NULL, 
               INTERNET_FLAG_KEEP_CONNECTION); 
     } 
     else 
     { 
      pSession = new CMyInternetSession (TEXT("SmGen"), 
               1, 
               INTERNET_OPEN_TYPE_PRECONFIG, 
               NULL, 
               NULL, 
               0); 
     } 
     if (pSession) 
     { 
      pSession->SetOwnerDialog (m_pOwner); 
      pHttpConn = pSession->GetHttpConnection (csServerName, (INTERNET_PORT)nPort, NULL, NULL); 

      if (pHttpConn) 
      { 
       dwFlags = INTERNET_FLAG_RELOAD | 
         INTERNET_FLAG_DONT_CACHE;  
       pHttpFile = pHttpConn->OpenRequest (CHttpConnection::HTTP_VERB_GET, 
                csObjectName + TEXT("?") + csHTTP, 
                NULL, 
                1, 
                NULL, 
                NULL, 
                dwFlags); 
       if (pHttpFile) 
       { 
       pHttpFile->AddRequestHeaders (csHeaders); 

       if (pHttpFile->SendRequest()) 
       { 
        pHttpFile->QueryInfoStatusCode (dwResult); 
        bRetryWithAuth = FALSE; 

        switch (dwResult) 
        { 
         case HTTP_STATUS_OK: 
          // log success 
          break; 

         case HTTP_STATUS_PROXY_AUTH_REQ: 
          bRetryWithAuth = TRUE; 
          break; 

         default: 
          // log failure 
          break; 
        } 

        if (bRetryWithAuth) 
        { 
         csProxyUsr = m_pOwner->GetProxyUsername(); 
         csProxyPwd = m_pOwner->GetProxyPassword(); 

         pHttpConn->SetOption (INTERNET_OPTION_PROXY_USERNAME, 
              csProxyUsr.GetBuffer(1), 
              csProxyUsr.GetLength()); 
         csProxyUsr.ReleaseBuffer(); 

         pHttpConn->SetOption (INTERNET_OPTION_PROXY_PASSWORD, 
              csProxyPwd.GetBuffer(1), 
              csProxyPwd.GetLength()); 
         csProxyPwd.ReleaseBuffer(); 

         if (pHttpFile->SendRequest()) 
         { 
          // ... TIMEOUT 

現在解決問題。問題是第二個SendRequest不會失敗或拋出另一個錯誤,它只是超出。過了一會兒,我得到了通過我的包裝處理程序拋出的CInternetException 12002(超時)。這有點煩人。不用說,SMS永遠不會到達。

代理服務器地址的格式爲a.b.c.d:8080,以消除DNS作爲致病因素。我的MIS部門向我保證,我提供的用戶名和密碼是有效的(如果我傳遞了錯誤的uid/pwd,它只會回覆到407錯誤,所以我知道他們至少會得到代理)。

我已經經歷過在這裏和在線上都能找到的一切,而且我無處可去。只要使用INTERNET_OPEN_TYPE_PRECONFIG,並希望系統能夠自動獲取所需的所有內容,如果你擁有的只是一個代理服務器,就不會起作用。

請記住,代碼的非代理相關功能沒有任何問題,因爲如果我通過擦除提供服務器ip:port的註冊表項來消除代理,則它將再次躍入生命。

我完全難住了。有沒有人見過這個?我不抱希望,因爲大約有沒有回覆代理認證查詢的數量...

編輯:

我已經轉換該代碼使用WINHTTP,因爲有一個MS樣本覆蓋代理(與身份驗證),並且WinInet反正被棄用。現在一切正常。

+0

如果你知道你到了代理......也許用Wireshark探聽會產生一些有用的信息?或者也許小提琴手? – dgnorton

回答

-1

通常在客戶端收到響應後關閉HTTP連接。 因此,當你發送你的第二個請求與身份驗證的細節代理將關閉連接(或至少停止接收)。

所以你必須再次調用OpenRequest來建立一個新的連接。

+0

與MSDN文檔相矛盾的是,我只需要重新發送,但很容易就可以嘗試,所以我明天早上就會發布它並報告回來。 –

+0

不,重新創建請求不起作用。 –

+0

收到響應後,HTTP連接不會關閉。如果真的如此,網絡通信會變慢很多。 –