问题是,如果您运行一次下面的代码会成功,但如果您在程序的同一生命周期内运行两次则会失败。
var request = (HttpWebRequest)WebRequest.Create("https://google.com");
var response = (HttpWebResponse)await request.GetResponseAsync();
我有 .NET Core 3.0 和 SDK 版本 3.0.100 .
复制:
dotnet new console -n test-ssl
cd test-ssl
. Program.cs
. using System;
using System.IO;
using System.Net;
using System.Threading.Tasks;
namespace test_ssl
{
class Program
{
static async Task Main(string[] args)
{
await CallGoogle();
await CallGoogle();
}
private static async Task CallGoogle()
{
var request = (HttpWebRequest)WebRequest.Create("https://google.com");
var response = (HttpWebResponse)await request.GetResponseAsync();
var jsonResponse = new StreamReader(response.GetResponseStream()).ReadToEnd();
Console.WriteLine(jsonResponse);
}
}
}
dotnet run
. 这将崩溃,但有以下异常:
Unhandled exception. System.Net.WebException: The SSL connection could not be established, see inner exception. The handshake failed due to an unexpected packet format.
---> System.Net.Http.HttpRequestException: The SSL connection could not be established, see inner exception.
---> System.IO.IOException: The handshake failed due to an unexpected packet format.
at System.Net.Security.SslStream.StartReadFrame(Byte[] buffer, Int32 readBytes, AsyncProtocolRequest asyncRequest)
at System.Net.Security.SslStream.PartialFrameCallback(AsyncProtocolRequest asyncRequest)
--- End of stack trace from previous location where exception was thrown ---
at System.Net.Security.SslStream.ThrowIfExceptional()
at System.Net.Security.SslStream.InternalEndProcessAuthentication(LazyAsyncResult lazyResult)
at System.Net.Security.SslStream.EndProcessAuthentication(IAsyncResult result)
at System.Net.Security.SslStream.EndAuthenticateAsClient(IAsyncResult asyncResult)
at System.Net.Security.SslStream.<>c.<AuthenticateAsClientAsync>b__65_1(IAsyncResult iar)
at System.Threading.Tasks.TaskFactory`1.FromAsyncCoreLogic(IAsyncResult iar, Func`2 endFunction, Action`1 endAction, Task`1 promise, Boolean requiresSynchronization)
--- End of stack trace from previous location where exception was thrown ---
at System.Net.Http.ConnectHelper.EstablishSslConnectionAsyncCore(Stream stream, SslClientAuthenticationOptions sslOptions, CancellationToken cancellationToken)
--- End of inner exception stack trace ---
at System.Net.Http.ConnectHelper.EstablishSslConnectionAsyncCore(Stream stream, SslClientAuthenticationOptions sslOptions, CancellationToken cancellationToken)
at System.Net.Http.HttpConnectionPool.ConnectAsync(HttpRequestMessage request, Boolean allowHttp2, CancellationToken cancellationToken)
at System.Net.Http.HttpConnectionPool.CreateHttp11ConnectionAsync(HttpRequestMessage request, CancellationToken cancellationToken)
at System.Net.Http.HttpConnectionPool.GetHttpConnectionAsync(HttpRequestMessage request, CancellationToken cancellationToken)
at System.Net.Http.HttpConnectionPool.SendWithRetryAsync(HttpRequestMessage request, Boolean doRequestAuth, CancellationToken cancellationToken)
at System.Net.Http.RedirectHandler.SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
at System.Net.Http.HttpClient.FinishSendAsyncUnbuffered(Task`1 sendTask, HttpRequestMessage request, CancellationTokenSource cts, Boolean disposeCts)
at System.Net.HttpWebRequest.SendRequest()
at System.Net.HttpWebRequest.EndGetResponse(IAsyncResult asyncResult)
--- End of inner exception stack trace ---
at System.Net.HttpWebRequest.EndGetResponse(IAsyncResult asyncResult)
at System.Net.WebRequest.<>c.<GetResponseAsync>b__68_2(IAsyncResult iar)
at System.Threading.Tasks.TaskFactory`1.FromAsyncCoreLogic(IAsyncResult iar, Func`2 endFunction, Action`1 endAction, Task`1 promise, Boolean requiresSynchronization)
--- End of stack trace from previous location where exception was thrown ---
at test_ssl.Program.CallGoogle() in C:\Users\me\source\Workspaces\tests\test-ssl\Program.cs:line 19
at test_ssl.Program.Main(String[] args) in C:\Users\me\source\Workspaces\tests\test-ssl\Program.cs:line 13
at test_ssl.Program.<Main>(String[] args)
为什么第二次会失败?
此问题也发布在 github 上的 .NET Core 中,因为它似乎与此相关:https://github.com/dotnet/core/issues/3847
进一步测试以缩小问题范围
.NET Framework 4.8 - 工作
使用 .NET Framework 4.8 控制台应用程序但是确实有效。所以用原来的
Program.cs
文件在这里工作。似乎真正的问题在于 .NET Core 3.0 Docker 中的 .NET Core 3.0 - 工作
docker run --rm -it mcr.microsoft.com/dotnet/core/sdk:3.0
dotnet new console -n test-ssl
cd test-ssl
// Replace content of Program.cs again.
dotnet run
// Everything works.
这让我相信我的机器上有些东西坏了,也许不是防火墙问题,因为最终 docker 容器将通过与我的计算机相同的防火墙到达谷歌。
Powershell 测试 - 工作
测试-ssl.ps1
Invoke-WebRequest -Uri 'https://google.com'
Invoke-WebRequest -Uri 'https://google.com'
HttpClient .NET Core 3.0 - 不工作
使用
HttpClient
给出同样的错误。所以替换CallGoogle
的内容以下不起作用:var client = new HttpClient();
await client.GetStringAsync("https://google.com");
最佳答案
似乎该系统一定已经以某种方式损坏了,因为它基本上在其他任何地方都可以正常工作。有一台正在工作的新电脑。
关于c# - 由于 SSL 握手异常,.NET Core 3.0 上的 WebRequest 第二次失败,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58937402/