httpclient.GetAsync: базовое соединение было закрыто: при отправке произошла непредвиденная ошибка - PullRequest
0 голосов
/ 08 января 2019

У меня есть простой веб-API, который получает URL-адрес и генерирует короткий номер в виде короткого URL-адреса. Я создал консольное приложение VS, где я вызываю веб-интерфейс через объект HTTPClient. Когда я запускаю код в первый раз, он выдает следующую ошибку:

Сообщение об ошибке: Произошла одна или несколько ошибок.

InnerException: System.Net.Http.HttpRequestException: при отправке запроса произошла ошибка. ---> System.Net.WebException: основное соединение было закрыто: при отправке произошла непредвиденная ошибка. ---> System.IO.IOException: невозможно прочитать данные из транспортного соединения: существующее соединение было принудительно закрыто удаленным хостом. ---> System.Net.Sockets.SocketException: существующее соединение было принудительно закрыто удаленным хостом в System.Net.Sockets.Socket.EndReceive (IAsyncResult asyncResult) в System.Net.Sockets.NetworkStream.EndRead (IAsyncResult asyncResult) --- Конец внутренней трассировки стека исключений --- в System.Net.TlsStream.EndWrite (IAsyncResult asyncResult) в System.Net.ConnectStream.WriteHeadersCallback (IAsyncResult ar) --- Конец внутренней трассировки стека исключений --- в System .Net.HttpWebRequest.EndGetResponse (IAsyncResult asyncResult) в System.Net.Http.HttpClientHandler.GetResponseCallback (IAsyncResult ar) --- Конец внутренней трассировки стека исключений ---

Это код, который я использую для вызова веб-API. Вызов веб-API через браузер работает просто отлично.

static void Main(string[] args)
{
    string url = "https://app1/api/AddUrl?longUrl=http://google.com";
    var result = GetTinyUrl(url).Result;
    Console.WriteLine(result.ShortUrl);     
}

protected static async Task<UrlResponse> GetUrl(string baseUrl)
{
    HttpClientHandler handler = new HttpClientHandler();
    handler.UseDefaultCredentials = true;

    var client = new HttpClient(handler);

    var response = client.GetAsync(baseUrl).Result;
    if (response.IsSuccessStatusCode)
    {
        HttpResponseMessage response1 = response;
        response.EnsureSuccessStatusCode();
        var resp = await response.Content.ReadAsStringAsync();
        var result = JsonConvert.DeserializeObject<UrlResponse>(resp);
        return result;
    }

    return null;
}

Ответы [ 3 ]

0 голосов
/ 08 января 2019

Микширование .Result блокировка вызовов с асинхронным ожиданием может привести к взаимоблокировке.

Если вы используете асинхронное ожидание, тогда идите асинхронно до конца и избегайте создания нового экземпляра HttpClient для каждого вызова, так как это может привести к истощению в носке.

static Lazy<HttpClient> http = new Lazy<HttpClient>(() => {
    //Handle TLS protocols
    System.Net.ServicePointManager.SecurityProtocol =
        System.Net.SecurityProtocolType.Tls
        | System.Net.SecurityProtocolType.Tls11
        | System.Net.SecurityProtocolType.Tls12;

    var handler = new HttpClientHandler() {
        UseDefaultCredentials = true
    };

    var client = new HttpClient(handler);
    return client;
});

protected static async Task<UrlResponse> GetUrl(string baseUrl) {
    var client = http.Value;

    var response = await client.GetAsync(baseUrl); //Remove .Result and just await
    if (response.IsSuccessStatusCode) {
        HttpResponseMessage response1 = response;
        response.EnsureSuccessStatusCode();
        var resp = await response.Content.ReadAsStringAsync();
        var result = JsonConvert.DeserializeObject<UrlResponse>(resp);
        return result;
    }
    return null;
}

Поскольку это консольное приложение и только асинхронный вызов вызывается только одним потоком, вам нужно изменить способ вызова асинхронного метода в main

static void Main(string[] args) {
    string url = "https://app1/api/AddUrl?longUrl=http://google.com";
    var result = GetTinyUrl(url).GetAwaiter().GetResult(); //<-- 
    Console.WriteLine(result.ShortUrl);     
}

Ссылка Async / Await - Лучшие практики в асинхронном программировании

0 голосов
/ 02 августа 2019

Просто скажу, что я часами смотрел на похожую проблему при подключении к лазурной службе, которую я пишу.

Не могу понять, почему почтальон работал нормально, но мой код с треском провалился. Точно так же другие URL, которые я пробовал в своем коде, работали нормально или давали ожидаемые сбои.

В конце концов, причиной сбоев стало то, что я забыл понизить Минимальная версия TLS в Настройки TLS / SSL blade-сервер !!

Я думаю, что старые версии HttpClient могут работать только с TLS v1.0.

0 голосов
/ 08 января 2019

Обычно я не советую использовать HttpClient для веб-запросов, иногда ему нравится неправильно работать с различными веб-API. Я настоятельно рекомендую вам использовать HttpWebRequest. Вы можете правильно обработать HTTP-запрос с полным контролем и получить лучший общий результат.

string uri = "https://api.foo.com/bar";

var httpWebRequest = (HttpWebRequest)WebRequest.Create(uri);
httpWebRequest.ContentType = "application/json";
httpWebRequest.Method = "GET"; // PUT, POST, DELETE, etc
//httpWebRequest.ContentLength = 0; // sometimes you need to send zero (depending on API)
HttpWebResponse httpResponse = (HttpWebResponse)await httpWebRequest.GetResponseAsync();

using (var streamReader = new StreamReader(httpResponse.GetResponseStream()))
{
    var response = streamReader.ReadToEnd();
    // this is your code here...
    var result = JsonConvert.DeserializeObject<UrlResponse>(response);
    return result;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...