C# HttpWebRequest.GetResponse()一直超时

C# HttpWebRequest.GetResponse()一直超时,c#,.net,httpwebrequest,mtgox,C#,.net,Httpwebrequest,Mtgox,我编写了一个简单的C#函数,通过以下API调用从MtGox检索交易历史: https://data.mtgox.com/api/1/BTCUSD/trades?since=<trade_id> 我从tid=0(交易id)开始获取数据(从一开始)。对于每个请求,我都会收到包含1000个交易详细信息的回复。对于下一个请求,我总是发送上一个响应中的交易id。它只适用于4个请求和响应。但在此之后,下面的一行抛出一个“System.Net.WebException”,表示“操作已超时”: 事

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

https://data.mtgox.com/api/1/BTCUSD/trades?since=<trade_id>
我从tid=0(交易id)开始获取数据(从一开始)。对于每个请求,我都会收到包含1000个交易详细信息的回复。对于下一个请求,我总是发送上一个响应中的交易id。它只适用于4个请求和响应。但在此之后,下面的一行抛出一个“System.Net.WebException”,表示“操作已超时”:

事实如下:

  • 捕获异常并重试会导致相同的异常
  • 默认的HttpWebRequest.Timeout和.ReadWriteTimeout已经足够高(超过一分钟)
  • 将HttpWebRequest.KeepAlive更改为false也无法解决任何问题
  • 它似乎总是在浏览器中工作,即使功能出现故障
  • 从中检索响应没有问题
  • 在异常发生之前,成功响应的数量每天都在变化(但浏览器始终工作)
  • 从上次失败的交易id开始会立即导致异常
  • 相反,从主线程调用此函数仍然会导致异常
  • 在另一台机器上运行它不起作用
  • 从不同的IP运行它不起作用
  • 增加线程。请求之间的睡眠没有帮助

你知道什么地方出了问题吗?

有两种超时。客户端超时和服务器超时。您是否尝试过这样做:

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

尝试类似的方法…

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

下面是调用RESTAPI的最后一种方法

        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;
        }
    }
我也有同样的问题。 对我来说,修复方法非常简单,只需将HttpWebResponse代码包装在using块中

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

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

值得一提的是,每次使用它时,我都会遇到同样的超时问题,即使调用的是我正在调用的服务器。在我的例子中,问题是我希望设置为application/json,而服务器并没有返回这个值。

这不是一个解决方案,只是一个替代方案: 现在我几乎只使用WebClient而不是HttpWebRequest。尤其是用于POST和PUT的WebClient.UploadString和WebClient.DownloadString。它们只是获取并返回字符串。通过这种方式,我不必处理streams对象,除非遇到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
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;
}
错误处理

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

是的,在处理大量请求时要小心,因为服务器会识别到这一点并关闭流量,因为这通常是拒绝服务,会在一段时间内阻塞您的IP以防止黑客攻击。如果你同意,你能点击accept吗?你能解释一下为什么用using块包装这个会改变行为吗?嗨@RussellMcDonnell。如果您向同一主机发出多个请求,并且未正确处理
WebResponse
,则通常会发生此问题。这就是为什么using block作为救世主来到这里。伙计们,你们是对的,我忘了处理我的响应。我当时应该使用using语句(我不知道)。我没有办法测试这是否会有帮助,虽然因为mtgox已经不存在了。但它很可能是解决方案,即使这是一篇旧帖子,也应该标记为正确答案。解决了我的问题,这比公认的答案要好。我只是认为我不需要处理,因为web请求本身没有实现IDisposable,我只是没有查看响应:)
KeepAlive=false?我在过去使用服务和keepAlive=true时有过一些不好的经历。尤其是SAP后端。从那时起,我设置keepAlive=false。我们松开了tcp套接字,但我们确定请求在两侧都已终止。我的请求没有关闭流写入程序。谢谢
// 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;
}
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);
}