HttpWebRequest.GetResponse()不断超时

我写了一个简单的C#函数,通过以下API调用从MtGox检索交易历史:

https://data.mtgox.com/api/1/BTCUSD/trades?since= 

记录在这里: https : //en.bitcoin.it/wiki/MtGox/API/HTTP/v1#Multi_currency_trades

这是function:

 string GetTradesOnline(Int64 tid) { Thread.Sleep(30000); // communicate string url = "https://data.mtgox.com/api/1/BTCUSD/trades?since=" + tid.ToString(); HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url); HttpWebResponse response = (HttpWebResponse)request.GetResponse(); StreamReader reader = new StreamReader(response.GetResponseStream()); string json = reader.ReadToEnd(); reader.Close(); reader.Dispose(); response.Close(); return json; } 

我从tid = 0(交易ID)开始获取数据(从一开始)。 对于每个请求,我收到一个包含1000个交易详情的回复。 我总是从上一个响应中发送交易ID以用于下一个请求。 它适用于4个请求和响应。 但在此之后,以下行抛出“System.Net.WebException”,表示“操作已超时”:

 HttpWebResponse response = (HttpWebResponse)request.GetResponse(); 

这是事实:

  • 捕获exception和重新处理会导致同样的exception
  • 默认的HttpWebRequest .Timeout和.ReadWriteTimeout已经足够高(超过一分钟)
  • 将HttpWebRequest.KeepAlive更改为false也没有解决任何问题
  • 它似乎总是在浏览器中工作,即使function失败
  • 从https://www.google.com检索响应没有问题
  • exception变化之前成功响应的数量每天都不同(但浏览器始终有效)
  • 从上次失败的交易ID开始会立即导致exception
  • 从主线程调用此函数仍然导致exception
  • 在另一台机器上运行它不起作用
  • 从不同的IP运行它不起作用
  • 在请求之间增加Thread.Sleep没有帮助

什么可能是错的想法?

有两种超时。 客户端超时和服务器超时。 你有没有试过这样的事情:

 request.Timeout = Timeout.Infinite; request.KeepAlive = true; 

试试这样的事……

我有同样的问题。 对我来说,修复就像在使用块中包装HttpWebResponse代码一样简单。

 using (HttpWebResponse response = (HttpWebResponse) request.GetResponse()) { // Do your processings here.... } 

详细信息 :当对同一主机发出多个请求并且WebResponse未正确处理时,通常会发生此问题。 这就是using block将正确处理WebResponse对象从而解决问题的地方。

我刚刚遇到类似的问题,通过ssl在LINUX服务器上调用REST服务。 在尝试了许多不同的配置方案后,我发现我必须在http头中发送UserAgent。

这是我调用REST API的最终方法。

  private static string RunWebRequest(string url, string json) { HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url); // Header request.ContentType = "application/json"; request.Method = "POST"; request.AllowAutoRedirect = false; request.KeepAlive = false; request.Timeout = 30000; request.ReadWriteTimeout = 30000; request.UserAgent = "test.net"; request.Accept = "application/json"; request.ProtocolVersion = HttpVersion.Version11; request.Headers.Add("Accept-Language","de_DE"); ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls; ServicePointManager.ServerCertificateValidationCallback = delegate { return true; }; byte[] bytes = Encoding.UTF8.GetBytes(json); request.ContentLength = bytes.Length; using (var writer = request.GetRequestStream()) { writer.Write(bytes, 0, bytes.Length); writer.Flush(); writer.Close(); } var httpResponse = (HttpWebResponse)request.GetResponse(); using (var streamReader = new StreamReader(httpResponse.GetResponseStream())) { var jsonReturn = streamReader.ReadToEnd(); return jsonReturn; } } 

值得一提的是,每次使用它时,我都会遇到与超时相同的问题,即使呼叫已经通过我正在呼叫的服务器。 在我的情况下的问题是我将Expect设置为application / json,而不是服务器返回的内容。

这不是一个解决方案,而只是一个替代方案:这些天我几乎只使用WebClient而不是HttpWebRequest。 特别是用于POST和PUT的WebClient.UploadString和WebClient.DownloadString。 这些只是简单地获取和返回字符 这种方式我不必处理流对象,除非我得到WebException。 我还可以根据需要使用WebClient.Headers [“Content-type”]设置内容类型。 using语句也可以通过为我调用Dispose来使生活更轻松。

很少有性能,我将System.Net.ServicePointManager.DefaultConnectionLimit设置为高,而是使用HttpClient及其同步调用的异步方法。

这就是我现在要做的

 string GetTradesOnline(Int64 tid) { using (var wc = new WebClient()) { return wc.DownloadString("https://data.mtgox.com/api/1/BTCUSD/trades?since=" + tid.ToString()); } } 

另外2个POST示例

 // POST string SubmitData(string data) { string response; using (var wc = new WebClient()) { wc.Headers["Content-type"] = "text/plain"; response = wc.UploadString("https://data.mtgox.com/api/1/BTCUSD/trades", "POST", data); } return response; } // POST: easily url encode multiple parameters string SubmitForm(string project, string subject, string sender, string message) { // url encoded query NameValueCollection query = HttpUtility.ParseQueryString(string.Empty); query.Add("project", project); query.Add("subject", subject); // url encoded data NameValueCollection data = HttpUtility.ParseQueryString(string.Empty); data.Add("sender", sender); data.Add("message", message); string response; using (var wc = new WebClient()) { wc.Headers[HttpRequestHeader.ContentType] = "application/x-www-form-urlencoded"; response = wc.UploadString( "https://data.mtgox.com/api/1/BTCUSD/trades?"+query.ToString() , WebRequestMethods.Http.Post , data.ToString() ); } return response; } 

error handling

 try { Console.WriteLine(GetTradesOnline(0)); string data = File.ReadAllText(@"C:\mydata.txt"); Console.WriteLine(SubmitData(data)); Console.WriteLine(SubmitForm("The Big Project", "Progress", "John Smith", "almost done")); } catch (WebException ex) { string msg; if (ex.Response != null) { // read response HTTP body using (var sr = new StreamReader(ex.Response.GetResponseStream())) msg = sr.ReadToEnd(); } else { msg = ex.Message; } Log(msg); throw; // re-throw without changing the stack trace }