Разница между 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();