c#httpclient无法从传输连接中读取数据:现有连接被远程主机强行关闭

发布于 2025-02-10 05:54:52 字数 2751 浏览 2 评论 0原文

我有一个.NET 6控制台应用程序,该应用程序浏览了网站列表,并检查有关SSL证书或即将到来的任何问题的任何问题。它适用于所有网站,除了托管在Azure上的夫妇之外。对于这些网站,当本地调试时,所有内容都按预期工作。但是,当控制台应用程序在Windows 2012服务器上运行时,HTTP GET请求失败了9/10次,此例外:

System.Net.Http.HttpRequestException: The SSL connection could not be established, see inner exception. ---> System.IO.IOException: Unable to read data from the transport connection: An existing connection was forcibly closed by the remote host.. ---> System.Net.Sockets.SocketException (10054): 

这些是我代码中的两个主要方法:

        async Task<CertStatus> SendRequest(string url)
        {
            _certStatus = new CertStatus
            {
                URL = url,
                Success = false
            };

            var handler = new HttpClientHandler();

            handler.ServerCertificateCustomValidationCallback = ServerCertificateCustomValidation;


            var client = new HttpClient(handler);

            try
            {
                var response = await client.GetAsync(url);

                response.EnsureSuccessStatusCode();

                _certStatus.Success = true;
            }
            catch (HttpRequestException ex)
            {
                _certStatus.ErrorMessage = ex.Message;
            }

            handler.Dispose();
            client.Dispose();

            var retval = _certStatus;

            return retval;
        }

        static bool ServerCertificateCustomValidation(HttpRequestMessage requestMessage, X509Certificate2? certificate, X509Chain? chain, SslPolicyErrors sslErrors)
        {
            if(_certStatus != null && certificate != null)
            {
                _certStatus.ExpireDate = DateTime.Parse(certificate.GetExpirationDateString());
            }


            Console.WriteLine($"Requested URI: {requestMessage.RequestUri}");
            Console.WriteLine($"Effective date: {certificate?.GetEffectiveDateString()}");
            Console.WriteLine($"Exp date: {certificate?.GetExpirationDateString()}");
            Console.WriteLine($"Issuer: {certificate?.Issuer}");
            Console.WriteLine($"Subject: {certificate?.Subject}");

            Console.WriteLine($"Errors: {sslErrors}");
            return sslErrors == SslPolicyErrors.None;
        }

我尝试将连接设置为TRUE

client.DefaultRequestHeaders.ConnectionClose = true;

增加超时

client.Timeout = TimeSpan.FromSeconds(120);

并设置设置SSL协议to TLS 1.2即使是.NET 6.0,但我认为这

System.Net.ServicePointManager.SecurityProtocol |= System.Net.SecurityProtocolType.Tls12;

对我可以尝试的是其他想法吗?对我来说,有时会成功并且有时失败,这对我来说很奇怪。 Windows Task Scheduler每天运行此控制台应用程序,并且在这些运行过程中始终失败。但是,当手动运行EXE时,有时会成功

I have a .NET 6 console app that goes through a list of websites and checks for any issues with SSL certificates or upcoming expiring certs. It works for all of the websites except a couple that are hosted on Azure. For these websites everything works as expected when debugging locally. However when the console app is run on a Windows 2012 server the http get request fails 9/10 times with this exception:

System.Net.Http.HttpRequestException: The SSL connection could not be established, see inner exception. ---> System.IO.IOException: Unable to read data from the transport connection: An existing connection was forcibly closed by the remote host.. ---> System.Net.Sockets.SocketException (10054): 

These are the two main methods in my code:

        async Task<CertStatus> SendRequest(string url)
        {
            _certStatus = new CertStatus
            {
                URL = url,
                Success = false
            };

            var handler = new HttpClientHandler();

            handler.ServerCertificateCustomValidationCallback = ServerCertificateCustomValidation;


            var client = new HttpClient(handler);

            try
            {
                var response = await client.GetAsync(url);

                response.EnsureSuccessStatusCode();

                _certStatus.Success = true;
            }
            catch (HttpRequestException ex)
            {
                _certStatus.ErrorMessage = ex.Message;
            }

            handler.Dispose();
            client.Dispose();

            var retval = _certStatus;

            return retval;
        }

        static bool ServerCertificateCustomValidation(HttpRequestMessage requestMessage, X509Certificate2? certificate, X509Chain? chain, SslPolicyErrors sslErrors)
        {
            if(_certStatus != null && certificate != null)
            {
                _certStatus.ExpireDate = DateTime.Parse(certificate.GetExpirationDateString());
            }


            Console.WriteLine(
quot;Requested URI: {requestMessage.RequestUri}");
            Console.WriteLine(
quot;Effective date: {certificate?.GetEffectiveDateString()}");
            Console.WriteLine(
quot;Exp date: {certificate?.GetExpirationDateString()}");
            Console.WriteLine(
quot;Issuer: {certificate?.Issuer}");
            Console.WriteLine(
quot;Subject: {certificate?.Subject}");

            Console.WriteLine(
quot;Errors: {sslErrors}");
            return sslErrors == SslPolicyErrors.None;
        }

I've tried setting ConnectionClose to true

client.DefaultRequestHeaders.ConnectionClose = true;

Increasing the the timeout

client.Timeout = TimeSpan.FromSeconds(120);

And setting the SSL protocol to tls 1.2 even though this is .Net 6.0 and I don't think that should be necessary

System.Net.ServicePointManager.SecurityProtocol |= System.Net.SecurityProtocolType.Tls12;

Any other ideas on what I could try? It's strange to me that it is sometimes successful and fails other times. This console app is ran daily by windows task scheduler and it has always failed during those runs. However, when the exe is ran manually it will sometimes succeed

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文