【问题标题】:Working C# code converted to Powershell results in SocketException转换为 Powershell 的工作 C# 代码导致 SocketException
【发布时间】:2019-04-13 11:58:20
【问题描述】:

我有以下成功调用 HTTP Post 端点的 C# 控制台应用程序:

class Program
{
    static void Main(string[] args)
    {
        HttpClient httpClient = new HttpClient();
        httpClient.BaseAddress = new Uri("https://DomainOne.azure-api.net");
        httpClient.DefaultRequestHeaders.Add("Ocp-Apim-Subscription-Key", "8b17badbbfe44e9e933453a8b4d8fc85");

        StringContent stringContent = new StringContent("\"hi\"", System.Text.Encoding.UTF8, "application/json");            
        Task<HttpResponseMessage> task = httpClient.PostAsync("integration/api/Result/CompanyOne", stringContent);
        HttpResponseMessage response = task.Result;

        var content = response.Content.ReadAsStringAsync().Result;
    }
}

这是我尝试使用的等效 Powershell 脚本:

$httpClient = New-Object 'System.Net.Http.HttpClient'
$httpClient.BaseAddress = New-Object 'System.Uri'('https://DomainOne.azure-api.net')
$httpClient.DefaultRequestHeaders.Add("Ocp-Apim-Subscription-Key", "8b17badbbfe44e9e933453a8b4d8fc85");

$stringContent = New-Object 'System.Net.Http.StringContent'('"hi"', [System.Text.Encoding]::UTF8, 'application/json')
$task = $httpClient.PostAsync('integration/api/Result/CompanyOne', $stringContent)
$response = $task.Result

$content = $response.Content.ReadAsStringAsync().Result

但是$task 对象包含以下内容:

System.AggregateException: One or more errors occurred. 
---> System.Net.Http.HttpRequestException: An error occurred while sending the request. 
---> System.Net.WebException: The underlying connection was closed: An unexpected error occurred on a send. 
---> 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: An existing connection was forcibly closed by the remote host
at System.Net.Sockets.Socket.EndReceive(IAsyncResult asyncResult)
at System.Net.Sockets.NetworkStream.EndRead(IAsyncResult asyncResult)
--- End of inner exception stack trace ---
at System.Net.TlsStream.EndWrite(IAsyncResult asyncResult)
at System.Net.ConnectStream.WriteHeadersCallback(IAsyncResult ar)
--- End of inner exception stack trace ---
at System.Net.HttpWebRequest.EndGetRequestStream(IAsyncResult asyncResult, TransportContext& context)
at System.Net.Http.HttpClientHandler.GetRequestStreamCallback(IAsyncResult ar)
--- End of inner exception stack trace ---

端点托管在 API 管理后面的开发 Azure 环境中,操作方法/控制器如下所示:

[ApiController]
[Route("api/[controller]")]
public class ResultController : ControllerBase
{                           
    [Route("{providerName}")]
    [HttpPost]
    public Task<bool> ReceiveMessage(HL7Message message)
    {
        return Task.FromResult(true);
    }
}

以下是 Azure API 管理中的协议设置:

为什么我在 Powershell 中得到 SocketException 而在 C# 中却没有,我怎样才能让它在 Powershell 中工作?

【问题讨论】:

  • 可能问题出在 tls 协商上。你能验证你使用的是什么 tls 版本吗?你能强制 tls 1.2 吗?
  • @AdminOfThings 我认为它使用的是 TLS 1.2。我用 APIM 中协议设置的屏幕截图更新了我的问题。
  • 尝试在脚本前面添加一行代码,专门将 SecvicePointManager.SecurityProtocol 设置为 TLS1.2。 docs.microsoft.com/en-us/dotnet/api/…
  • @RickRainey 谢谢!那行得通!如果你写一个答案,我可以接受。
  • 如果他发布任何内容,请务必接受@RickRainey 的回答。我发布只是为了让我们有一个答案,以防 Rick 决定不发布任何内容。

标签: azure powershell http asp.net-core azure-api-management


【解决方案1】:

基于Rick Rainey's helpful comment,您可以通过在HTTP调用之前添加以下代码行来强制使用TLS版本:

[System.Net.ServicePointManager]::SecurityProtocol = [System.Net.SecurityProtocolType]::Tls12

我认为这是正在使用的 .NET 版本的限制。 .NET 4.6 以下的任何版本都将默认使用非 1.2 的 TLS 版本。

【讨论】:

    猜你喜欢
    • 2011-01-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-07-03
    • 1970-01-01
    相关资源
    最近更新 更多