An existing connection was forcibly closed by the remote host

This error occured randomly in my project when I tried to read images from a HttpWebRequest. The exception is:

Exception: System.IO.IOException
Message: Unable to read data from the transport connection: An existing connection was forcibly closed by the remote host.

Nested Exception

Exception: System.Net.Sockets.SocketException Message: An existing connection was forcibly closed by the remote host
Source: System
at System.Net.Sockets.Socket.Receive(Byte[] buffer, Int32 offset, Int32 size, SocketFlags socketFlags)
at System.Net.Sockets.NetworkStream.Read(Byte[] buffer, Int32 offset, Int32 size)

Errors like these are very hard to find, and several forums (like this and this) have solutions, but none of them worked for me.

The error occurs in the following code, where I use a HttpWebRequest to retrieve an image from another server:

private Byte[] RetrieveAsset(Uri uri, out string contentType)
{
  try
  {
    Byte[] bytes;
    HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create(uri);
    webRequest.Headers.Add("UserAgent", "Pentia; MSI");
    using (WebResponse webResponse = webRequest.GetResponse())
    {
      contentType = webResponse.ContentType;
      using (Stream stream = webResponse.GetResponseStream())
      {
        using (MemoryStream memoryStream = new MemoryStream())
        {
          // Stream the response to a MemoryStream via the byte array buffer
          Byte[] buffer = new Byte[0x1000];

          Int32 bytesRead;
          while ((bytesRead = stream.Read(buffer, 0, buffer.Length)) > 0)
          {
            memoryStream.Write(buffer, 0, bytesRead);
          }
          bytes = memoryStream.ToArray();
        }
      }
    }
    return bytes;
  }
  catch (Exception ex)
  {
    throw new Exception("Failed to retrieve asset from '" + uri + "': " + ex.Message, ex);
  }
}

To solve my problem I needed 3 things, all of them in connection with the HttpWebRequest:

STEP 1: Disable KeepAlive

As Denis Pitcher describes on his blog, there is a bug in .NET that closes the connection prior to it being finished. Disabling KeepAlive closes the connection for every request:

webRequest.KeepAlive = false;

STEP 2: Set ProtocolVersion to Version10

Setting the ProtocolVersion to Version10 forces the HTTP requets to use HTTP 1.0. I can’t explain why it’s needed, but it is:

webRequest.ProtocolVersion = HttpVersion.Version10;

STEP3: Limiting the number of service points

As this MSDN article describes, The ConnectionLimit property sets the maximum number of connections that the ServicePoint object can make to an Internet resource. Apparently the server I am requesting data from is underpowered, why I have to limit my number of connections to it.

webRequest.ServicePoint.ConnectionLimit = 1;

Mircosoft states that the ConnectionLimit should be set at 12 connections per CPU (see this MSDN article, under “Performance Issues”) which in my case is 24 connections, but anything above 2 connections will force the connection to close.

SUMMARY:

The final function is this:

private Byte[] RetrieveAsset(Uri uri, out string contentType)
{
  try
  {
    Byte[] bytes;
    HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create(uri);
    webRequest.KeepAlive = false;
    webRequest.ProtocolVersion = HttpVersion.Version10;
    webRequest.ServicePoint.ConnectionLimit = 1;
    webRequest.Headers.Add("UserAgent", "Pentia; MSI");
    using (WebResponse webResponse = webRequest.GetResponse())
    {
      contentType = webResponse.ContentType;
      using (Stream stream = webResponse.GetResponseStream())
      {
        using (MemoryStream memoryStream = new MemoryStream())
        {
          // Stream the response to a MemoryStream via the byte array buffer
          Byte[] buffer = new Byte[0x1000];

          Int32 bytesRead;
          while ((bytesRead = stream.Read(buffer, 0, buffer.Length)) > 0)
          {
            memoryStream.Write(buffer, 0, bytesRead);
          }
          bytes = memoryStream.ToArray();
        }
      }
    }
    return bytes;
  }
  catch (Exception ex)
  {
    throw new Exception("Failed to retrieve asset from '" + uri + "': " + ex.Message, ex);
  }
}

This might not solve your problem, but it solved mine.

ADDITIONAL RESOURCES:

About briancaos

Developer at Pentia A/S since 2003. Have developed Web Applications using Sitecore Since Sitecore 4.1.
This entry was posted in .net, c#, General .NET and tagged , , , , , . Bookmark the permalink.

15 Responses to An existing connection was forcibly closed by the remote host

  1. Pingback: Unable to read data from the transport connection: The connection was closed « Brian Pedersen’s Sitecore and .NET Blog

  2. Dave says:

    I was having the exact problem intermittently when posting SOAP to a Java webservice.. The steps described above resolved it! Thank you very much!

    Like

  3. Chris says:

    Found this blog post through Google trying to solve the same issue. I was getting intermittent and random timeouts from an app trying to download image resources from the internet. The steps in this post solved my problem, so many thanks to Brian. FWIW, the main thing that solved my problem was this:

    webRequest.ProtocolVersion = HttpVersion.Version10;

    As soon as I added that, the random IOExceptions disappeared. I also added the keepAlive and connection limit per the post, but the HttpVersion was the thing that really did the trick for me.

    Like

  4. Tiago says:

    It did the trick, thank you! But for me, to make it to work, I only needed the keep alive to false.

    Like

  5. Antonio says:

    where can i find this code Please help me!?

    Like

  6. Pingback: VSTS & TeamCIty – Together everyone achieves more… | Well Technically…

  7. web page says:

    I think that iss among the such a lot important info for me.
    And i am glad reading your article. But should statement on few basic issues, The website style is ideal,
    the articles is iin point of fact great : D. Excellent job, cheers

    Like

  8. Magno Costa says:

    Great post, but I’m new to the language and I do not know where to implement the code described above. Could you help a beginner by providing an example of where I would put this?

    Like

  9. Pingback: Requesting Azure API Management URL’s | Brian Pedersen's Sitecore and .NET Blog

  10. Minhaj says:

    Same cryptic message. The solution mentioned in the blog works.

    Like

  11. Pingback: WebService Exception- A conexão subjacente foi fechada: Ocorreu um erro inesperado em um envio C#

  12. Pingback: WebService Exception – La connexion sous-jacente a été fermée: une erreur inattendue s’est produite lors d’un envoi. Langage C#

  13. Pingback: Исключение WebService – базовое соединение было закрыто: произошла непредвиденная ошибка при отправке C#

  14. Pingback: Web Service Service Exception: la conexión subyacente se cerró: se produjo un error inesperado en un envío C#

  15. Pingback: WebService Exception- The underlying connection was closed: An unexpected error occurred on a send

Leave a comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.