8

When creating, using, and disposing several HttpClients I notice that there are sockets left open in the TIME_WAIT status.

For example, after running the following:

using System.Net.Http;

namespace HttpClientTest
{
    public class Program
    {
        public static void Main(string[] args)
        {
            for (var i = 0; i < 10; i++)
            {
                using (var httpClient = new HttpClient())
                {
                   var result = httpClient.
                        GetAsync("http://stackoverflow.com/").
                        Result;
                }
            }
        }
    }
}

I notice with netstat, that sockets are left open:

TCP    10.200.60.168:2722     151.101.193.69:http    TIME_WAIT
TCP    10.200.60.168:2751     151.101.193.69:http    TIME_WAIT
TCP    10.200.60.168:2752     151.101.193.69:http    TIME_WAIT
TCP    10.200.60.168:2753     151.101.193.69:http    TIME_WAIT
TCP    10.200.60.168:2754     151.101.193.69:http    TIME_WAIT
TCP    10.200.60.168:2755     151.101.193.69:http    TIME_WAIT
TCP    10.200.60.168:2756     151.101.193.69:http    TIME_WAIT
TCP    10.200.60.168:2757     151.101.193.69:http    TIME_WAIT
TCP    10.200.60.168:2758     151.101.193.69:http    TIME_WAIT
TCP    10.200.60.168:2759     151.101.193.69:http    TIME_WAIT

Is this expected behavior? Do I need to explicitly set the Connection header value to close to prevent this?

httpClient.
    DefaultRequestHeaders.
    Connection.
    Add("close");
Benjamin Soddy
  • 557
  • 1
  • 6
  • 22

2 Answers2

9

Each instance of HttpClient pools its connections for better performance, but this means that each instance also leaves the pooled connections in TIME_WAIT when they are not in use.

HttpClient is actually thread-safe, reentrant, and designed for extended use; it should not be disposed of (even though it implements IDisposable) until your program exits. You should share one instance of HttpClient throughout your application to take advantage of this.

More information can be found here.

Bradley Uffner
  • 16,641
  • 3
  • 39
  • 76
  • 1
    This becomes much more obvious when looking at how header values are set. On the HttpClient directly, they are DefaultRequestHeaders, which implies that the HttpContent would have headers unique to the request and the HttpClient would be reused. The IDisposable inheritance was initially throwing me off. And also 80% of samples disposing the HttpClient. – Benjamin Soddy Sep 28 '16 at 19:42
1

From MSDN

every HttpClient instance uses its own connection pool, isolating its requests from requests executed by other HttpClient instances.

HttpClient pools connections for better performance.

BWA
  • 5,672
  • 7
  • 34
  • 45