C# HttpClient 现有连接被远程主机强行关闭
C# HttpClient An existing connection was forcibly closed by the remote host
我正在使用他们的 hosted page integration 与 Alternative Payments 进行集成。他们的 C# SDK 目前没有此集成可用,但如您所见,它非常简单,我做了一个小 class 来发送 post 请求并获得 JSON 响应。
我测试了 json object 我在 PostMan 和 cURL 上发送并且都工作,还有身份验证 header,所以我认为它们不是问题。这是我的 class:
的构造函数
public AlternativePaymentsCli(string apiSecretKey)
{
this._apiSecretKey = apiSecretKey;
_httpClient = new HttpClient();
_httpClient.DefaultRequestHeaders.Accept
.Add(new MediaTypeWithQualityHeaderValue("application/json"));
var authInfo = _apiSecretKey;
authInfo = Convert.ToBase64String(System.Text.ASCIIEncoding.ASCII.GetBytes(string.Format("{0}:", _apiSecretKey)));
// The two line below because I saw in an answer on Whosebug.
_httpClient.DefaultRequestHeaders.Add("Connection", "Keep-Alive");
_httpClient.DefaultRequestHeaders.Add("Keep-Alive", "3600");
_httpClient.DefaultRequestHeaders.UserAgent.ParseAdd("Anything.com custom client v1.0");
_httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", authInfo);
}
以及我post获取数据的方法:
public string CreateHostedPageTransaction(HostedPageRequest req)
{
var settings = new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore };
// I send this same json content on PostMan and it works. The json is not the problem
var content = new StringContent(JsonConvert.SerializeObject(req, settings), Encoding.UTF8, "application/json");
var response = _httpClient.PostAsync(this._baseUrl + "/transactions/hosted", content).Result;
var responseText = response.Content.ReadAsStringAsync().GetAwaiter().GetResult();
if (response.IsSuccessStatusCode)
return responseText;
return "";
}
然后我在 PostAsync 行收到此错误:An existing connection was forcibly closed by the remote host
。这是错误详情:
[SocketException (0x2746): An existing connection was forcibly closed by the remote host]
System.Net.Sockets.Socket.EndReceive(IAsyncResult asyncResult) +8192811
System.Net.Sockets.NetworkStream.EndRead(IAsyncResult asyncResult) +47
[IOException: Unable to read data from the transport connection: An existing connection was forcibly closed by the remote host.]
System.Net.TlsStream.EndWrite(IAsyncResult asyncResult) +294
System.Net.ConnectStream.WriteHeadersCallback(IAsyncResult ar) +149
[WebException: The underlying connection was closed: An unexpected error occurred on a send.]
System.Net.HttpWebRequest.EndGetRequestStream(IAsyncResult asyncResult, TransportContext& context) +324
System.Net.Http.HttpClientHandler.GetRequestStreamCallback(IAsyncResult ar) +137
[HttpRequestException: An error occurred while sending the request.]
我正在使用 C# 4.5,Asp.Net MVC。我一直在阅读相同错误的答案,到目前为止,其中 none 解决了我的问题。我在这段代码中遗漏了什么?
感谢您的帮助
我在您的代码示例中没有看到您在哪里设置 _baseUrl 的值,但我假设这是在某处完成的。我还假设因为这与付款有关,所以 URL 是 HTTPS。如果远程主机已禁用 TLS 1.0 而您的连接以 TLS 1.0 的形式进入,则可能会导致该行为。我知道 C# 4.6 默认启用 TLS 1.0/1.1/1.2 支持,但我认为 C# 4.6 仍然默认仅 SSL3/TLS 1.0,即使支持 TLS 1.1 和 1.2。如果这是问题的原因,您可以使用以下代码手动将 TLS 1.1 和 1.2 添加到已启用的值。
System.Net.ServicePointManager.SecurityProtocol |= SecurityProtocolType.Tls11 | SecurityProtocolType.Tls12;
如果您使用的是 .Net 4.0,则未定义 SecurityProtocolType.Tls11 和 SecurityProtocolType.Tls2,因此您可以使用下面的硬编码值。
ServicePointManager.SecurityProtocol = (SecurityProtocolType)3072;
可以在不更改代码的情况下解决问题,如中描述的类似问题:
将 Web 项目重新定位到 .Net 4.6+,然后更新 web.config 如下:
<system.web>
<compilation targetFramework="4.6" />
<httpRuntime targetFramework="4.6" />
</system.web>
这对我有用,第一行确保协议 ssl3
和 TLS1.2
,第二行忽略任何潜在的证书错误(忽略并继续 - 如过期的证书。):
ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3 | SecurityProtocolType.Tls12;
ServicePointManager.ServerCertificateValidationCallback += (sender, certificate, chain, sslPolicyErrors) => true;
对我来说,这个错误是由于忘记配置代理服务器造成的。
使用以下代码构造 HttpClient
为我的 .NET 4.7.2 应用程序解决了它:
var httpClientHandler = new HttpClientHandler { Proxy = WebRequest.GetSystemWebProxy() };
var httpClient = new HttpClient(httpClientHandler);
希望这对某人有所帮助。
我正在使用他们的 hosted page integration 与 Alternative Payments 进行集成。他们的 C# SDK 目前没有此集成可用,但如您所见,它非常简单,我做了一个小 class 来发送 post 请求并获得 JSON 响应。
我测试了 json object 我在 PostMan 和 cURL 上发送并且都工作,还有身份验证 header,所以我认为它们不是问题。这是我的 class:
的构造函数public AlternativePaymentsCli(string apiSecretKey)
{
this._apiSecretKey = apiSecretKey;
_httpClient = new HttpClient();
_httpClient.DefaultRequestHeaders.Accept
.Add(new MediaTypeWithQualityHeaderValue("application/json"));
var authInfo = _apiSecretKey;
authInfo = Convert.ToBase64String(System.Text.ASCIIEncoding.ASCII.GetBytes(string.Format("{0}:", _apiSecretKey)));
// The two line below because I saw in an answer on Whosebug.
_httpClient.DefaultRequestHeaders.Add("Connection", "Keep-Alive");
_httpClient.DefaultRequestHeaders.Add("Keep-Alive", "3600");
_httpClient.DefaultRequestHeaders.UserAgent.ParseAdd("Anything.com custom client v1.0");
_httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", authInfo);
}
以及我post获取数据的方法:
public string CreateHostedPageTransaction(HostedPageRequest req)
{
var settings = new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore };
// I send this same json content on PostMan and it works. The json is not the problem
var content = new StringContent(JsonConvert.SerializeObject(req, settings), Encoding.UTF8, "application/json");
var response = _httpClient.PostAsync(this._baseUrl + "/transactions/hosted", content).Result;
var responseText = response.Content.ReadAsStringAsync().GetAwaiter().GetResult();
if (response.IsSuccessStatusCode)
return responseText;
return "";
}
然后我在 PostAsync 行收到此错误:An existing connection was forcibly closed by the remote host
。这是错误详情:
[SocketException (0x2746): An existing connection was forcibly closed by the remote host]
System.Net.Sockets.Socket.EndReceive(IAsyncResult asyncResult) +8192811
System.Net.Sockets.NetworkStream.EndRead(IAsyncResult asyncResult) +47
[IOException: Unable to read data from the transport connection: An existing connection was forcibly closed by the remote host.]
System.Net.TlsStream.EndWrite(IAsyncResult asyncResult) +294
System.Net.ConnectStream.WriteHeadersCallback(IAsyncResult ar) +149
[WebException: The underlying connection was closed: An unexpected error occurred on a send.]
System.Net.HttpWebRequest.EndGetRequestStream(IAsyncResult asyncResult, TransportContext& context) +324
System.Net.Http.HttpClientHandler.GetRequestStreamCallback(IAsyncResult ar) +137
[HttpRequestException: An error occurred while sending the request.]
我正在使用 C# 4.5,Asp.Net MVC。我一直在阅读相同错误的答案,到目前为止,其中 none 解决了我的问题。我在这段代码中遗漏了什么?
感谢您的帮助
我在您的代码示例中没有看到您在哪里设置 _baseUrl 的值,但我假设这是在某处完成的。我还假设因为这与付款有关,所以 URL 是 HTTPS。如果远程主机已禁用 TLS 1.0 而您的连接以 TLS 1.0 的形式进入,则可能会导致该行为。我知道 C# 4.6 默认启用 TLS 1.0/1.1/1.2 支持,但我认为 C# 4.6 仍然默认仅 SSL3/TLS 1.0,即使支持 TLS 1.1 和 1.2。如果这是问题的原因,您可以使用以下代码手动将 TLS 1.1 和 1.2 添加到已启用的值。
System.Net.ServicePointManager.SecurityProtocol |= SecurityProtocolType.Tls11 | SecurityProtocolType.Tls12;
如果您使用的是 .Net 4.0,则未定义 SecurityProtocolType.Tls11 和 SecurityProtocolType.Tls2,因此您可以使用下面的硬编码值。
ServicePointManager.SecurityProtocol = (SecurityProtocolType)3072;
可以在不更改代码的情况下解决问题,如
将 Web 项目重新定位到 .Net 4.6+,然后更新 web.config 如下:
<system.web>
<compilation targetFramework="4.6" />
<httpRuntime targetFramework="4.6" />
</system.web>
这对我有用,第一行确保协议 ssl3
和 TLS1.2
,第二行忽略任何潜在的证书错误(忽略并继续 - 如过期的证书。):
ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3 | SecurityProtocolType.Tls12;
ServicePointManager.ServerCertificateValidationCallback += (sender, certificate, chain, sslPolicyErrors) => true;
对我来说,这个错误是由于忘记配置代理服务器造成的。
使用以下代码构造 HttpClient
为我的 .NET 4.7.2 应用程序解决了它:
var httpClientHandler = new HttpClientHandler { Proxy = WebRequest.GetSystemWebProxy() };
var httpClient = new HttpClient(httpClientHandler);
希望这对某人有所帮助。