1

Given the following settings:

ServicePointManager.DefaultConnectionLimit = 24;

And the following code:

public static async Task<HttpWebResponse> GetResponseAsync(this Uri uri, bool autoRedirect)
{
    var request = (HttpWebRequest)WebRequest.Create(uri);
    request.UserAgent = "Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/32.0.1700.107 Safari/537.36";
    request.AllowAutoRedirect = autoRedirect;
    request.Timeout = -1;
    request.ReadWriteTimeout = -1;

    var response = await request.GetResponseAsync();
    return (HttpWebResponse)response;
}

public static async Task<PageInfo> GetPageAsync(Uri uri)
{
    using (var response = await uri.GetResponseAsync(false))
    {
        using(var responseStream = response.GetResponseStream())
        {
            var pageInfo = new PageInfo();

            using (var reader = new StreamReader(responseStream))
            {
                try
                {
                    pageInfo.HTML = await reader.ReadToEndAsync();
                }
                catch(Exception ex)
                {
                    Console.WriteLine(ex.ToString());
                }

                return pageInfo;
            }
        }
    }
}

This setup will at 15-20 concurrent web requests, after 1.000 requests throw the following exception:

Unable to read data from the transport connection: An existing connection was forcibly closed by the remote host

The exception is throwen at the line pageInfo.HTML = await reader.ReadToEndAsync().


I've tried firing up fiddler, and inspect the statuscode/headers for the url it throws an exception on, when reading from the stream. - And as expected, it's a new url each time - and all returning either 301 or 200. Therefore I can eliminate that it's the host who fails.

Setting the ServicePointManager.DefaultConnectionLimit to a lower value, helps for some reason. - So do changing the line await reader.ReadToEndAsync() to reader.ReadToEnd().

It seems that some kind of timeout kicks in, that closes the stream before the data is read. - This would also explain why setting the DefaultConnectionLimit to a lower value, has an impact. The is at best a wild guess, and even if it's true I do not see how to change that timeout. I've set both Timeout and ReadWriteTimeout for the WebRequest (see the GetResponseAsync extension method above).

Any suggestions/hints are greatly appreciated.

ebb
  • 9,297
  • 18
  • 72
  • 123
  • Try setting `request.KeepAlive = true;` – noseratio Feb 20 '14 at 09:06
  • @Noseratio, Thanks for the suggestion. I've tried setting `request.KeepAlive = true;` - but it still throws an exception. – ebb Feb 20 '14 at 09:13
  • ebb, have your tried `HttpClient` instead of `WebRequest`? – noseratio Feb 20 '14 at 09:17
  • @Noseratio, I just ran a test with `HttpClient` instead of `WebRequest`. - It throws a different exception, but I'm quite sure the reason behind both is the same. The exception in threw was: `A task was canceled`. – ebb Feb 20 '14 at 09:41
  • Read the Comments of [this question](http://stackoverflow.com/questions/21903837/httpwebresponse-get-stuck-while-running-in-a-loop) – L.B Feb 20 '14 at 10:02
  • @L.B, Unfortunately it has nothing to do with throttling, as I'm making a request to a new host each time. Also every disposable object is wrapped in a `using` statmenet in my code, so this is not the problem either. - But thanks for the hint! – ebb Feb 20 '14 at 10:33
  • Are you sure it had the same error on the same run you checked with Fiddler? I ask because "An existing connection was forcibly closed by the remote host" is *exactly* the same as a socket-level error message that indicates the remote sent an unexpected RST. – Stephen Cleary Feb 20 '14 at 11:52
  • @StephenCleary, I'm absolutely sure. The URL that it threw the exception at, had returned 200 (OK), and I could see the entire response (HTML) in fiddler. – ebb Feb 20 '14 at 12:12
  • @ebb: I don't mean the same URL; I mean Fiddler showed you the full response and your code showed an error for the same request. – Stephen Cleary Feb 20 '14 at 12:16
  • @StephenCleary, That's right. – ebb Feb 20 '14 at 12:19
  • @ebb,OTOH, have you tried `request.KeepAlive = false` ? – noseratio Feb 22 '14 at 02:08

0 Answers0