【问题标题】:Difference between GetHostEntry and GetHostByName?GetHostEntry 和 GetHostByName 之间的区别?
【发布时间】:2012-03-17 15:03:03
【问题描述】:

在MSDN 上提到GetHostByName 已过时。替换为GetHostEntry。他们有什么区别?

【问题讨论】:

    标签: c# dns gethostbyname


    【解决方案1】:

    GetHostEntry 似乎做了更多的错误检查,并且还支持Network Tracing

    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;
    }
    

    【讨论】:

    • 如果您发现自己像我一样遇到那些过时的错误,您可以轻松地在您的代码中将GetHostByName() 更改为GetHostEntry()。
    • 并不是那么简单。 GetHostByAddress 如果无法执行反向 DNS 查找,即使在有效 IP 上也会失败。作为一个粗略的经验法则,看起来前端 GetHostEntry 旨在仅返回 实际 DNS 条目,而 GetHostByName 旨在以任何方式提供 IP 地址。因此,您传递给GetHostByName 的任何IP 地址都将被简单地解析并返回,但GetHostEntry 只会返回该IP如果您可以获得反向DNS 响应。这使得GetHostEntry 不太适合对来自用户输入的目标地址进行通用处理。
    【解决方案2】:

    首先,重要的是要认识到这些是 UNIX 套接字库的包装器,它公开了函数 inet_aton(等效于 IPAddress.Parse)、gethostbyname(由 Dns.GetHostByName 包装)和 gethostbyaddr(包装由Dns.GetHostByAddress)。微软随后在这些基础上添加了Dns.GetHostEntry实用功能。

    在思考了 Dns.GetHostByName 和 Dns.GetHostEntry 之间的哲学差异之后,我得出的结论是,Microsoft 决定他们为 DNS 查找公开的主要 API 应该尝试只返回 实际的 DNS 条目 em>。

    在 UNIX 套接字级别,gethostbyname 可以采用 IP 地址或主机名。如果您提供的是 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 类的内部实现细节,但它的精神很容易在您自己的代码中复制,例如:

    if (!IPAddress.TryParse(userInput, out var addressToWhichToConnect))
      addressToWhichToConnect = Dns.GetHostEntry(userInput).AddressList.First();
    

    【讨论】:

      猜你喜欢
      • 2013-07-12
      • 2014-05-30
      • 1970-01-01
      • 2021-12-25
      • 2020-05-10
      • 2014-09-20
      • 2010-10-28
      • 2015-10-04
      • 2012-08-12
      相关资源
      最近更新 更多