2013-04-17 164 views
1

我有許多ASP.NET網站和使用相同代碼「登錄」到第三方網站的web服務。這包括基本上使用WebRequest通過我的憑證對網站的登錄頁面執行HTTP POST,將產生的Cookie存儲在CookieContainer中,並在任何以下WebRequest中使用該CookieContainer將我的網站授權給第三方網站上的頁面。由於意外的數據包格式,WebRequest握手失敗

的代碼基本如下:

public LoginResults Login() 
    { 
     // Create the webrequest 
     var request = CreateInitialWebRequest(LOGIN_URL); 
     request.AllowAutoRedirect = false; 

     // Set the cookiecontainer, which will be filled with the authentication cookies 
     this.cookieContainer = new CookieContainer(); 
     request.CookieContainer = this.cookieContainer; 

     // Set the username and pw in a HTTP POST call 
     SetPostContent(request, string.Format(LOGIN_PARAMETERS, this.Username, this.Password)); 

     // Read the response 
     using (var httpWebResponse = (HttpWebResponse)request.GetResponse()) 
     { 
      using (var responseStream = httpWebResponse.GetResponseStream()) 
      { 
       // Omitted: 
       // read response and determine if login was successful 
      } 
     } 
    } 

    private HttpWebRequest CreateInitialWebRequest(string uri) 
    { 
     var request = (HttpWebRequest)WebRequest.Create(uri); 
     ServicePointManager.ServerCertificateValidationCallback = delegate { return true; }; 
     return request; 
    } 

    private HttpWebRequest CreateWebRequest(string uri) 
    { 
     var request = this.CreateInitialWebRequest(uri); 
     request.CookieContainer = cookieContainer; 
     request.Accept = "image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/x-ms-application, application/vnd.ms-xpsdocument, application/xaml+xml, application/x-ms-xbap, application/x-shockwave-flash, */*"; 
     request.UserAgent = "User-Agent: Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0; SLCC1; .NET CLR 2.0.50727; Media Center PC 5.0; .NET CLR 3.0.04506; .NET CLR 3.5.21022)"; 
     request.Method = "GET"; 
     request.Timeout = 10000; // 10 sec 
     return request; 
    } 

    private static void SetPostContent(HttpWebRequest req, string postData) 
    { 
     req.Method = "POST"; 
     byte[] bytes = new ASCIIEncoding().GetBytes(postData); 
     req.ContentType = "application/x-www-form-urlencoded"; 
     req.ContentLength = (long)bytes.Length; 
     ((WebRequest)req).GetRequestStream().Write(bytes, 0, bytes.Length); 
     ((WebRequest)req).GetRequestStream().Close(); 
    } 

該代碼已經工作了很長的時間(幾個月,過了半年)。自從這個週末以來,它已經開始失敗(我估計有90%的時間,但不是100%的時間)。我一直看到的錯誤是:System.Net.WebException:底層連接已關閉:發送時發生意外錯誤。 ---> System.IO.IOException:由於意外的數據包格式,握手失敗。 的堆棧跟蹤如下:

System.Net.WebException: The underlying connection was closed: An unexpected error occurred on a send. ---> System.IO.IOException: The handshake failed due to an unexpected packet format. 
at System.Net.Security.SslState.StartReadFrame(Byte[] buffer, Int32 readBytes, AsyncProtocolRequest asyncRequest) 
at System.Net.Security.SslState.StartReceiveBlob(Byte[] buffer, AsyncProtocolRequest asyncRequest) 
at System.Net.Security.SslState.CheckCompletionBeforeNextReceive(ProtocolToken message, AsyncProtocolRequest asyncRequest) 
at System.Net.Security.SslState.StartSendBlob(Byte[] incoming, Int32 count, AsyncProtocolRequest asyncRequest) 
at System.Net.Security.SslState.ForceAuthentication(Boolean receiveFirst, Byte[] buffer, AsyncProtocolRequest asyncRequest) 
at System.Net.Security.SslState.ProcessAuthentication(LazyAsyncResult lazyResult) 
at System.Net.TlsStream.CallProcessAuthentication(Object state) 
at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx) 
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx) 
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state) 
at System.Net.TlsStream.ProcessAuthentication(LazyAsyncResult result) 
at System.Net.TlsStream.Write(Byte[] buffer, Int32 offset, Int32 size) 
at System.Net.PooledStream.Write(Byte[] buffer, Int32 offset, Int32 size) 
at System.Net.ConnectStream.WriteHeaders(Boolean async) 
--- End of inner exception stack trace --- 
at System.Net.HttpWebRequest.GetRequestStream(TransportContext& context) 
at System.Net.HttpWebRequest.GetRequestStream() 
at iRacingForumService.HttpPost.SetPostContent(HttpWebRequest req, String postData) 
at iRacingForumService.HttpPost.Login() 

當我谷歌這個錯誤我一直看到的唯一的解決辦法是禁用的WebRequest和/或設置ProtocolVersion到HttpVersion10的KeepAlive屬性。我嘗試了兩種(每種組合都可能),沒有任何幫助。

錯誤並不總是出現,但是當它確實出現時,我可以繼續嘗試所有我喜歡的,我會不斷地收到錯誤。如果我離開它幾分鐘,然後再試一次,我有可能會發揮作用(一旦它結束,它將繼續工作一段時間)。

奇怪的是,我沒有改變我的任何事情;這段代碼已經運行了好幾個月沒有問題。第三方網站完全有可能改變某些事情,或者我的虛擬主機提供商改變了一些東西。但爲了萬一我可以採取一些措施來解決這個問題,我想問我是否做錯了什麼。

我可以聯繫第三方網站(可能不會得到回覆)或我的網站主持人,但我需要更好地瞭解到底發生了什麼問題,因爲把這個錯誤告訴他們可能無濟於事。

那麼,有什麼我可以做的,還是有一個很好的理由,爲什麼我突然在我的所有網站(他們都連接到同一個第三方網站)看到這個錯誤?

感謝

+0

試圖找出使用嗅探器(如Wireshark - http://www.wireshark.org/) – Maxim

+0

1.你是否在代理或防火牆? 2.您可以使用Fiddler來嗅探兩臺服務器之間的數據包請求嗎? –

+0

1.我不知道,我說的是在web服務器上運行這個代碼(我租用的),所以我假設有一個防火牆涉及。我沒有足夠的權限訪問服務器(除了Web控制面板),所以我無法檢查(儘管我可以請求支持)。 2.我不知道如何使用Fiddler,我已經嘗試了幾次,但沒有任何特別的地方在我控制之外的兩臺服務器之間進行通信。 –

回答

0

由於這種情況間歇性地,您可能需要與服務器管理員聯繫,瞭解怎麼回事。由於加載,配置錯誤或其他網絡問題,服務器可能會拒絕或關閉連接。