.Net核心HttpClient错误?SocketException:现有连接被远程主机强行关闭

ca9*_*3d9 6 c# .net-core

下面的代码在完整的.Net Framework控制台程序中运行,没有任何错误。但是,在.Net core 2.1中运行时,出现以下错误。

System.AggregateException
  HResult = 0x80131500
  Message =发生一个或多个错误。
  来源= System.Private.CoreLib
  堆栈跟踪:
   在System.Threading.Tasks.Task`1.GetResultCore(Boolean waitCompletionNotification)
   在C:\ source \ repos \ ConsoleApp1 \ Program.cs:line 38中的ConsoleApp1.Program.requestString(String url)
   在C:\ source \ repos \ ConsoleApp1 \ Program.cs:line 13中的ConsoleApp1.Program.Main(String [] args)

内部例外1:
HttpRequestException:无法建立SSL连接,请参阅内部异常。

内部例外2:
IOException:无法从传输连接中读取数据:现有连接被远程主机强行关闭。

内部例外3:
SocketException:现有连接被远程主机强行关闭

码:

class Program
{
    static void Main(string[] args)
    {
        var url = "https://google.com";
        var (statusCode, html) = requestString(url);
        Console.WriteLine("%d %s", statusCode, html);
    }

    static CookieContainer cc = new CookieContainer();

    static HttpClientHandler handler = new HttpClientHandler { AllowAutoRedirect = false, CookieContainer = cc };

    public static async Task<(int statusCode, string content)> requestStringAsync(string url)
    {
        ServicePointManager.ServerCertificateValidationCallback += (sender, cert, chain, sslPolicyErrors) => true;
        ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls12;
                                                                     // | SecurityProtocolType.Ssl3;
        using (var request = new HttpRequestMessage { RequestUri = new Uri(url), Method = HttpMethod.Get })
        using (var client = new HttpClient(handler))
        {
            var response = await client.SendAsync(request); // Error (actual line)
            // response.EnsureSuccessStatusCode() |> ignore
            var statusCode = (int)response.StatusCode;
            var content = await response.Content.ReadAsStringAsync();
            return (statusCode, content);
        }
    }

    public static (int statusCode, string content) requestString(string url)
    {
        return requestStringAsync(url).Result;
    }
}
Run Code Online (Sandbox Code Playgroud)

Joh*_*n H 7

.NET Core 2.1 Preview的一个错误提到了此问题。这可能是原因。但是,我还注意到您的TLS设置不正确。您当前正在启用它,但会覆盖已设置的所有其他协议。代替这个:

ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls12;
Run Code Online (Sandbox Code Playgroud)

您应该使用此:

ServicePointManager.SecurityProtocol |= SecurityProtocolType.Tls | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls12;
// ----------------------------------^
Run Code Online (Sandbox Code Playgroud)

我认为这是一个附带问题,但值得一视同仁。

更新资料

上面提到的GitHub问题进行了讨论,最终链接到.NET Core 2.1 SDK Preview 2的官方公告。它具有以下说法:

套接字性能和SocketsHttpHandler

我们对.NET Core 2.1中的套接字进行了重大改进。套接字是传出和传入网络通信的基础。.NET Core 2.1中的高层网络API(包括HttpClient和Kestrel)现在基于.NET套接字。在早期版本中,这些更高级别的API是基于本机网络实现的。

...

您可以使用以下机制之一来配置进程以使用较旧的HttpClientHandler:

从代码中,使用AppContext类:

AppContext.SetSwitch("System.Net.Http.UseSocketsHttpHandler", false);
Run Code Online (Sandbox Code Playgroud)

也可以通过配置文件来设置AppContext开关。

可以通过环境变量DOTNET_SYSTEM_NET_HTTP_USESOCKETSHTTPHANDLER实现相同的目的。要选择退出,请将值设置为false或0。