2013-05-24 5 views
9

я написал простую C# функцию, чтобы получить историю торговли из MtGox со следующим API вызова:HttpWebRequest.GetResponse() продолжает получать таймаут

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

описываемых здесь: https://en.bitcoin.it/wiki/MtGox/API/HTTP/v1#Multi_currency_trades

вот функция:

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 (торговый идентификатор), чтобы получить данные (с самого начала). для каждого запроса я получаю ответ, содержащий 1000 торговых данных. я всегда отправляю торговый идентификатор из предыдущего ответа для следующего запроса. он отлично работает для ровно 4 запроса & ответов. но после того, что следующая строка бросает «System.Net.WebException», говоря, что «операция истекла»:

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

вот факты:

  • отлов исключения и retying сохраняет вызывая то же исключение
  • по умолчанию HttpWebRequest .Timeout и .ReadWriteTimeout уже достаточно высоки (более минуты)
  • изменения HttpWebRequest.KeepAlive лжи не решить что-нибудь либо
  • , кажется, всегда работает в браузере, даже в то время как функция терпит неудачу
  • он не имеет никаких проблем retrieveing ​​ответа от https://www.google.com
  • суммы успешных ответов перед исключениями меняются изо дня в день (но браузер всегда работает)
  • начиная с торговли ид, что не удалось в последний раз вызывает исключение немедленно
  • вызова этой функции из главного потока, а не все еще вызвал исключение
  • работает его на другой машине не работал
  • ру nning его с другого IP не работает
  • увеличение Thread.Sleep Inbetween запросов не помогает

какие-либо идеи о том, что может быть не так?

ответ

13

Существует два вида тайм-аутов. Таймаут клиента и таймаут сервера. Вы пробовали делать что-то вроде этого:

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

Попробуйте что-то вроде этого ...

+0

Я просто попробовал то, что вы предложили. на этот раз он загрузил 5 ответов, так что это похоже на улучшение. но затем я продолжаю получать «Удаленный сервер возвратил ошибку: (504)« Время ожидания шлюза »(которое отличается от« Операция тайм-аута ») – symbiont

+0

Я предполагаю, что это проблема на стороне сервера? – symbiont

+0

безразлично. он по-прежнему работает в моем браузере (firefox). – symbiont

5

Я просто имел подобные проблемы, требующие Служба REST на LINUX сервере через SSL. После нескольких сценариев конфигурации я узнал, что должен был отправить UserAgent в http-заголовок.

Вот мой последний метод вызова API REST.

 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; 
     } 
    } 
11

У меня была такая же проблема. Для меня исправление было так же просто, как обертывание кода HttpWebResponse при использовании блока.

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

Деталь: Эта проблема обычно происходит, когда несколько запросов на тот же хост, и WebResponse не расположен должным образом. Именно здесь блок using правильно разместит объект WebResponse и тем самым решает проблему.

+0

Не могли бы вы объяснить, почему обертывание этого в блоке using изменило бы поведение? –

+1

Привет @RussellMcDonnell. Эта проблема обычно возникает, если вы делаете несколько запросов на один и тот же хост, а 'WebResponse' не используется правильно. Вот почему блок использования приходит сюда как спаситель. – Habeeb

0

Для чего это стоит, у меня возникали те же проблемы с таймаутами каждый раз, когда я их использовал, даже если звонки перешли на сервер, на который я звонил. Проблема в моем случае состояла в том, что у меня был Expect установлен application/json, когда это не то, что сервер возвращал.

Смежные вопросы