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 these ads

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.

2 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!

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s