Разница между GetHostEntry и GetHostByName?

На MSDN это упоминает GetHostByName устарел. Замена GetHostEntry, В чем их разница?

1 ответ

Решение

Похоже, что GetHostEntry немного больше проверяет ошибки, а также поддерживает отслеживание сети

GetHostByName декомпилировано:

public static IPHostEntry GetHostByName(string hostName)
{
  if (hostName == null)
    throw new ArgumentNullException("hostName");
  Dns.s_DnsPermission.Demand();
  IPAddress address;
  if (IPAddress.TryParse(hostName, out address))
    return Dns.GetUnresolveAnswer(address);
  else
    return Dns.InternalGetHostByName(hostName, false);
}

GetHostEntry Декомпилировано:

public static IPHostEntry GetHostEntry(string hostNameOrAddress)
{
  if (Logging.On)
    Logging.Enter(Logging.Sockets, "DNS", "GetHostEntry", hostNameOrAddress);
  Dns.s_DnsPermission.Demand();
  if (hostNameOrAddress == null)
    throw new ArgumentNullException("hostNameOrAddress");
  IPAddress address;
  IPHostEntry ipHostEntry;
  if (IPAddress.TryParse(hostNameOrAddress, out address))
  {
    if (((object) address).Equals((object) IPAddress.Any) || ((object) address).Equals((object) IPAddress.IPv6Any))
      throw new ArgumentException(SR.GetString("net_invalid_ip_addr"), "hostNameOrAddress");
    ipHostEntry = Dns.InternalGetHostByAddress(address, true);
  }
  else
    ipHostEntry = Dns.InternalGetHostByName(hostNameOrAddress, true);
  if (Logging.On)
    Logging.Exit(Logging.Sockets, "DNS", "GetHostEntry", (object) ipHostEntry);
  return ipHostEntry;
}

Во-первых, важно понимать, что это оболочки библиотеки сокетов UNIX, которая предоставляет функции inet_aton (эквивалентно IPAddress.Parse), gethostbyname (завернутый Dns.GetHostByName) а также gethostbyaddr (завернутый Dns.GetHostByAddress). Впоследствии Microsoft добавилаDns.GetHostEntry функция полезности, основанная на них.

Поразмыслив над философской разницей между Dns.GetHostByName а также Dns.GetHostEntry, Я пришел к выводу, что Microsoft решила, что основной API, который они предоставляют для поиска DNS, должен пытаться возвращать только фактические записи DNS.

На уровне сокетов UNIX gethostbynameможет принимать либо IP-адрес, либо имя хоста. Это явно задокументировано как анализ IP-адреса, если вы его указали. Но он также явно задокументирован как поддерживающий только адреса IPv4. Таким образом, разработчикам рекомендуется использовать функциюgetaddrinfo вместо этого, который выполняет более сложный поиск с участием службы, к которой вы также хотите подключиться, и которая поддерживает семейства адресов, отличные от IPv4.

Microsoft использовала другой подход в своей оболочке. Они все еще считаютGetHostByNameбыть устаревшим, но вместо того, чтобы связывать поиск с базой данных служб, они решили создать функцию, которая возвращает фактическую запись физического хоста DNS, которую вы запрашиваете. Недостаточно того, что вы, возможно, предоставите строку с действительным адресом в ней, если нет записи DNS, тогдаGetHostEntryпотерпит неудачу, потому что в этом вся его цель. Таким образом, если вы передадите имя хоста вGetHostEntry, он выполняет прямой поиск DNS, и если вы передадите IP-адрес в GetHostEntry, он выполняет обратный поиск в DNS. В любом случае возвращенная структура сообщит вам как имя записи DNS, так и связанный с ней адрес, но если связанной записи нет, единственное, что вы получите, - это ошибка.

Если вы хотите обрабатывать пользовательский ввод, который предоставляет цель для подключения, GetHostEntry не совсем подходит, потому что, если пользователь вводит специальный IP-адрес, он может не разрешить его, хотя, поскольку это IP-адрес, у вас есть все необходимое для подключения. GetHostByNameэто именно та функция, которая вам нужна в этом случае, но Microsoft решила отказаться от нее. Учитывая устаревание, идиома будет повторять подход "сначала попытайтесь разобрать", который @Faisai Mansoor продемонстрировал в декомпилированномGetHostByName функция:

// Microsoft's internal code for GetHostByName:
if (IPAddress.TryParse(hostName, out address))
  return Dns.GetUnresolveAnswer(address);
else
  return Dns.InternalGetHostByName(hostName, false);

При этом используются детали внутренней реализации Dns class, но его дух легко воспроизвести в вашем собственном коде, например:

if (!IPAddress.TryParse(userInput, out var addressToWhichToConnect))
  addressToWhichToConnect = Dns.GetHostEntry(userInput).AddressList.First();
Другие вопросы по тегам