2013-04-17 126 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

由于这种情况间歇性地,您可能需要与服务器管理员联系,了解怎么回事。由于加载,配置错误或其他网络问题,服务器可能会拒绝或关闭连接。