System.Net.WebException: удаленное имя не может быть разрешено:
Я тестирую конечную точку, с которой у меня возникают некоторые проблемы.
Я просто использую HttpClient
в цикле, который выполняет запрос каждый час.
var httpClient = new HttpClient();
var message = httpClient.GetAsync(url).Result;
Console.WriteLine(message.StatusCode);
Время от времени я получаю это исключение:
System.Net.Http.HttpRequestException: при отправке запроса произошла ошибка. ---> System.Net.WebException: удаленное имя не может быть разрешено: 'xxx'
Опыт показывает, что сразу после исключения можно получить доступ к URL. В браузере вы просто обновляете страницу и все хорошо.
Я до сих пор не получил никаких отчетов от пользователей, испытывающих это, поэтому мне интересно, является ли это просто локальной проблемой здесь, но мог бы использовать небольшую информацию, чтобы помочь диагностировать.
Есть ли способ проверить, если удаленное имя не может быть разрешено, вызвано проблемой DNS или проблемой веб-сервера из исключений? Могу ли я получить больше информации из HttpCLient
или мне нужны более продвинутые диагностические инструменты?
4 ответа
Вероятно, это связано с проблемой подключения к локальной сети (но также возможна ошибка DNS).
Это может случиться, вы мало что можете сделать.
Что бы я посоветовал всегда заключать этот (связанный с сетью) код в цикл с try
/catch
блок (как также предлагается здесь для других ошибочных операций). Обработайте известные исключения, подождите немного (скажем, 1000 мс) и повторите попытку (скажем, 3 раза). Только если все время произошел сбой, вы можете выйти / сообщить об ошибке своим пользователям. Очень сырой пример, как это:
private const int NumberOfRetries = 3;
private const int DelayOnRetry = 1000;
public static HttpResponseMessage GetFromUrl(string url) {
for (int i=1; i <= NumberOfRetries; ++i) {
try {
// Also consider to make this method async and await this.
// Note that in "real code" client MUST be disposed
return new HttpClient().GetAsync(url).Result;
}
catch (Exception e) {
// DO BETTER THAN THIS! Catch what you want to handle,
// not all exceptions worth a retry. Documentation and many
// tests will help you to narrow a limited subset of
// exceptions and error codes.
// Last one, (re)throw exception and exit
if (i == NumberOfRetries)
throw;
// Many network related errors will recover "automatically"
// after some time, exact delay is pretty arbitrary and
// should be determined with some tests. 1 second is pretty
// "good" for local I/O operations but network issues may
// need longer delays.
Thread.Sleep(DelayOnRetry);
}
}
}
Более современная и лучше реализованная версия:
public static async Task<HttpResponseMessage> GetFromUrlAsync(string url) {
using (var client = new HttpClient()) {
for (int i=1; i <= NumberOfRetries; ++i) {
try {
return await client.GetAsync(url);
}
catch (Exception e) when (i < NumberOfRetries) {
await Task.Delay(DelayOnRetry);
}
}
}
}
У меня была похожая проблема при попытке доступа к сервису (старый сервис ASMX). Вызов будет работать при доступе через IP, однако при вызове с псевдонимом я не смогу определить удаленное имя.
Добавил следующее в конфиг, и это решило проблему:
<system.net>
<defaultProxy enabled="true">
</defaultProxy>
</system.net>
Откройте файл hosts, расположенный по адресу: **C:\windows\system32\drivers\etc**.
Добавьте следующее в конец этого файла:
YourServerIP YourDNS
Пример:
198.168.1.1 maps.google.com
эта проблема наверняка связана с HttpClient в С #. Этот клиент предназначен для его повторного использования. Поскольку сокеты не закрываются напрямую после удаления HttpClient. Хорошее объяснение содержится в этом сообщении в блоге (https://www.nimaara.com/beware-of-the-net-httpclient/).
Вы должны справиться с тем, что ваша таблица поиска DNS устарела. В сообщении блога вы также найдете информацию о том, как это сделать.
ServicePointManager.FindServicePoint(endpoint).ConnectionLeaseTimeout = (int)TimeSpan.FromMinutes(1).TotalMilliseconds;
ServicePointManager.DnsRefreshTimeout = (int)1.Minutes().TotalMilliseconds;