受欢迎的博客标签

C# HttpClient Class

Published

 

在创建 HttpClient 时,其中常用的传入参数类型就是 HttpClientHandler 和 SocketsHttpHandler 类型

从 .NET Core 2.1 开始,默认的 HttpClient 底层的网络通讯实现就是靠 System.Net.Http.SocketsHttpHandler 实现的,替代了原先的 HttpClientHandler 类型。

在 dotnet 6 采用的 HttpClient 底层使用的是 SocketsHttpHandler 类型作为默认的网络通讯。

无论你在 HttpClient 传入的参数类型是 SocketsHttpHandler 还是 HttpClientHandler 类型,在 dotnet 6 都会实际上调用到 SocketsHttpHandler 类型

 

HttpClient - HttpClientHandler 

public static HttpClient CreateHttpClient()
{
    var handler = new HttpClientHandler()
    {
       ServerCertificateCustomValidationCallback = HttpClientHandler.DangerousAcceptAnyServerCertificateValidator
    };
    return new HttpClient(handler);
}

Note

There is really no reason to use SocketsHttpHandler instead of HttpClientHandler in .Net 5 or 6 because HttpClientHandler simply redirects all calls to a internal SocketsHttpHandler instance.

HttpClientHandler source code 

HttpClientHandler 的底层实现就是使用 SocketsHttpHandler 来实现

using HttpHandlerType = System.Net.Http.SocketsHttpHandler;

    public partial class HttpClientHandler : HttpMessageHandler
    {
        private readonly HttpHandlerType _underlyingHandler;

        private HttpMessageHandler Handler
            => _underlyingHandler;

        public HttpClientHandler()
        {
            _underlyingHandler = new HttpHandlerType();

            ClientCertificateOptions = ClientCertificateOption.Manual;
        }

        protected internal override HttpResponseMessage Send(HttpRequestMessage request, CancellationToken cancellationToken) =>
            Handler.Send(request, cancellationToken);

        protected internal override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) =>
            Handler.SendAsync(request, cancellationToken);

        // 忽略其他逻辑
    }

 

 

HttpClient - SocketsHttpHandler

public static HttpClient CreateHttpClient()
{
   var sslOptions = new SslClientAuthenticationOptions
   {
      // Leave certs unvalidated for debugging
      RemoteCertificateValidationCallback = delegate { return true; },
   };

   var handler = new SocketsHttpHandler()
   {
      SslOptions = sslOptions,
   };

    return new HttpClient(handler);
}

or

var socketsHttpHandler = new SocketsHttpHandler()
{
    // 这个可以设置连接的超时时间
    ConnectTimeout = TimeSpan.FromSeconds(10),
    //PooledConnectionIdleTimeout = TimeSpan.FromSeconds(100),
    // HttpClient only resolves DNS entries when a connection is created. It does not track any time to live (TTL) durations specified by the DNS server. If DNS entries change regularly, which can happen in some container scenarios, the client won't respect those updates. To solve this issue, you can limit the lifetime of the connection by setting the SocketsHttpHandler.PooledConnectionLifetime property, so that DNS lookup is required when the connection is replaced.
    PooledConnectionLifetime = TimeSpan.FromSeconds(1000),
    SslOptions = new SslClientAuthenticationOptions()
    {
        RemoteCertificateValidationCallback = (sender, certificate, chain, errors) => true, // HttpClientHandler.DangerousAcceptAnyServerCertificateValidator 忽略证书错误
    },
};

var httpClient = new HttpClient(socketsHttpHandler);

 

public sealed class SocketsHttpHandler : HttpMessageHandler

source:https://dev.to/tswiftma/switching-from-httpclienthandler-to-socketshttphandler-17h3

 

HttpClient - SocketsHttpHandler – ConnectCallback

ConnectCallback enables customizing new connection creation. It is called every time a new TCP connection is opened. The callback can be used to establish in-process transport, to control DNS resolution, to control general or platform-specific options of the underlying socket, or just to be notified whenever a new connection is opened. The following remarks apply to the callback:

It is passed DnsEndPoint determining the remote endpoint and HttpRequestMessage which initiated the connection creation.
Since SocketsHttpHandler provides connection pooling, the created connection might be used to handle multiple subsequent requests, not just the initial one.
A new Stream is expected to be returned.
The callback should not try to establish a TLS session. This is handled afterwards by SocketsHttpHandler.

source:https://devblogs.microsoft.com/dotnet/net-5-new-networking-improvements/

 

 

Useful links

dotnet 6 HttpClientHandler 和 SocketsHttpHandler 有什么差别

https://cloud.tencent.com/developer/article/2071585

 

HttpClient原理

https://www.cnblogs.com/xiaoxiaotank/p/16273773.html