【问题标题】:How does InetAddress class getLocalHost() return "Preferred" IP address?InetAddress 类 getLocalHost() 如何返回“首选”IP 地址?
【发布时间】:2013-02-11 17:28:40
【问题描述】:

我开始深入研究通过 Java 获取 IP 地址。我知道一台机器可以通过不同的网络接口拥有各种 IP,所以我对我发现的一些示例代码感到有些困惑,这些示例代码似乎返回了“首选”IP 地址(根据 Windows 7 命令行 ipconfig /all 首选)。

当我在本地计算机上运行以下代码时,会返回 26 个 NetworkInterface 对象,其中一些具有多个 InetAddress 对象(包括“首选”对象):

Enumeration<NetworkInterface> eNI = null;
    NetworkInterface ni = null;

    Enumeration<InetAddress> eIA = null;
    InetAddress ia = null;

    try {
        eNI = NetworkInterface.getNetworkInterfaces();
    } catch (Exception e) {
    }

    while (eNI.hasMoreElements()) {

        ni = eNI.nextElement();
        System.out.println("NtwkIntfc name: " + ni.getName());
        System.out.println("NtwkIntfc disp name: " + ni.getDisplayName());

        try {
            System.out.println("NtwkIntfc hardware addr: " + Hex.encodeHexString(ni.getHardwareAddress()));
        } catch (Exception e) {
        }

        eIA = ni.getInetAddresses();

        while (eIA.hasMoreElements()) {

            ia = eIA.nextElement();

            System.out.println("InetAddress host address: " + ia.getHostAddress());
            System.out.println("InetAddress host name: " + ia.getHostName());

        }
    }

然而,这个简单得多的代码只返回“首选”IPv4 地址:

try {
        InetAddress thisIp = InetAddress.getLocalHost();  
        System.out.println("IP:" + thisIp.getHostAddress());
    } catch (Exception e) {
        e.printStackTrace();
    }

我似乎找不到将其标识为“首选”的 NetworkInterface(以及其中的 InetAddress)属性/方法,所以我想知道类方法 InetAddress.getLocalHost() 是如何做到的?此外,此首选 IP 是标准网络概念还是某种类型的 Windows 特定概念?

谢谢。

【问题讨论】:

    标签: java networking


    【解决方案1】:

    查看网络设置中的指标。还可以查看 Windows 7 命令行下的“路由打印”。我认为指标越低,适配器就越“首选”。

    【讨论】:

      【解决方案2】:

      查看InetAddress.getLocalHost()的源代码。

      简单地说,它获取绑定到主机名的 IP 地址,并从返回的 IP 地址数组中返回第一个条目。

      除了它是映射到机器主机名的地址之外,我没有看到任何特定于此的东西首选(请注意,一台机器也可以有多个名称)

      【讨论】:

      • 啊,非常有帮助,以前没接触过这个网站,谢谢。
      【解决方案3】:

      我认为“首选”可能以某种方式指代路由表中最通用的条目。谁知道那些 Windows 疯子在想什么。

      但是,此地址也可能对应于最有可能是公共 IP/由 DHCP 分配的地址。如果您正在寻找最有可能公开/用于打开端口的地址的代码,这就是我用来获取 IPv4 地址的代码:

      public static InetAddress getNetworkAddr() {
          InetAddress localAddr = null;
      
          // Find our public IP address
          Enumeration<NetworkInterface> netInterfaces;
          try {
              netInterfaces = NetworkInterface.getNetworkInterfaces();
              while (netInterfaces.hasMoreElements()) {               
                  NetworkInterface ni = (NetworkInterface) netInterfaces.nextElement();               
                  Enumeration<InetAddress> addresses = ni.getInetAddresses();             
                  while( addresses.hasMoreElements() ) {
                      InetAddress addr = addresses.nextElement();
      
                      // System.out.println("Checking out " + ni.getName() + " with address " + addr.toString());
      
                      if (!addr.isSiteLocalAddress() && 
                              !addr.isLoopbackAddress() && 
                              !addr.isLinkLocalAddress() &&
                              addr.getHostAddress().indexOf(":") == -1) { // MAC/IPv6 address detection
                          System.out.println("Interface " + ni.getName()
                                  + " seems to be InternetInterface. I'll take address " + addr.toString());
                          System.out.println("Associated hostname: " + addr.getHostName());
                          localAddr = addr;
                          break;
                      }
                  }   
                  if( localAddr != null ) break;
              }
          } catch( NoSuchElementException e) {
              System.out.println("Couldn't find a public address");
              localAddr = null;
          } catch (SocketException e) {
              e.printStackTrace();
              localAddr = null;
          }
      
          return localAddr;
      }
      

      【讨论】:

        【解决方案4】:

        另一种与套接字一起工作的解决方案(不是最好的)

        Socket socket = new Socket("www.somesite.com", 80); 
        InetAddress localhost = socket.getLocalAddress(); 
        System.out.println("Address of local host is " + localhost);
        socket.close(); 
        

        【讨论】:

          猜你喜欢
          • 2011-08-14
          • 2018-12-29
          • 2015-10-08
          • 1970-01-01
          • 1970-01-01
          • 2020-10-28
          • 1970-01-01
          • 1970-01-01
          • 2015-06-21
          相关资源
          最近更新 更多