【问题标题】:java InetAddress.getLocalHost(); returns 127.0.0.1 ... how to get REAL IP?java InetAddress.getLocalHost();返回 127.0.0.1 ...如何获得真实 IP?
【发布时间】:2011-01-23 18:58:39
【问题描述】:

我正在编写一个简单的网络应用程序。我需要知道我的机器在网络上的真实 IP,比如 192.168.1.3 。 getLocalHost 返回 127.0.0.1 (在Linux上,不知道在windows上是不是一样)。怎么做?

【问题讨论】:

  • 在我的窗口中,System.out.println(InetAddress.getLocalHost().getHostAddress());打印 10.50.16.136
  • 有趣...正确答案,虽然它不起作用?
  • 这在 SO 上很常见,错误的回答会被标记为已回答。
  • @sfussenegger 127.0.1.1 是 Debian 的东西(Ubuntu 是从它衍生而来的)。 IIRC,如果你使用 DHCP,你会得到它。这允许报告一个固定的 IP 地址(我相信这对于 GNOME 的顺利运行是必要的)。所以 127.0.1.1 是一个“真实 IP”地址。 (顺便说一句:192.168.* 是非互联网 IP 地址。)
  • @tom 是的,我知道它是什么。我只是想知道这是对这个问题的正确答案(“我需要知道我的机器在网络上的真实 ip”)。

标签: java networking


【解决方案1】:

如果您真的想使用机器上的所有 IP 地址,您可以使用 NetworkInterface 类获取这些地址。当然,您需要实际使用哪一个,但这取决于您使用它的目的,或者您可能需要扩展使用它的方式以考虑多个地址。

import java.net.*;
import java.util.*;

public class ShowInterfaces
{
        public static void main(String[] args) throws Exception
        {
                System.out.println("Host addr: " + InetAddress.getLocalHost().getHostAddress());  // often returns "127.0.0.1"
                Enumeration<NetworkInterface> n = NetworkInterface.getNetworkInterfaces();
                for (; n.hasMoreElements();)
                {
                        NetworkInterface e = n.nextElement();
                        System.out.println("Interface: " + e.getName());
                        Enumeration<InetAddress> a = e.getInetAddresses();
                        for (; a.hasMoreElements();)
                        {
                                InetAddress addr = a.nextElement();
                                System.out.println("  " + addr.getHostAddress());
                        }
                }
        }
}

【讨论】:

  • while (x.hasMoreElements()) {} 会比 for (;x.hasMoreElements();) {} 更整洁
【解决方案2】:

由于机器可能有多个地址,因此很难确定哪一个适合您。通常,您希望系统根据其路由表分配 IP。由于结果取决于您要连接的 IP,因此有一个简单的技巧:只需创建一个连接并查看您从操作系统获得的地址:

// output on my machine: "192.168.1.102"
Socket s = new Socket("192.168.1.1", 80);
System.out.println(s.getLocalAddress().getHostAddress());
s.close();

// output on my machine: "127.0.1.1"
System.out.println(InetAddress.getLocalHost().getHostAddress());

我不确定是否可以在不建立连接的情况下执行此操作。我想我曾经设法用 Perl(或 C?)做到这一点,但不要问我关于 Java 的事。我认为有可能在不实际连接的情况下创建一个 UDP 套接字(DatagramSocket)。

如果途中有 NAT 路由器,您将无法获得远程主机将看到的 IP。但是,正如您以 192.* 为例,我认为您不在乎。

【讨论】:

  • 但是你怎么知道网关IP(192.168.1.1)首先打开套接字?
  • @mrod 你应该使用“你想连接的IP”。例如,您可以使用new Socket("www.google.com", 80); 来获取路由到 Internet 的接口的 IP 地址
  • 对,如果我们假设用例是“连接到另一台主机”,这将起作用:)。如果用例是审计或任何其他没有与另一台主机连接的情况,我猜如果配置了多个 IP 地址(除非我们知道特定的首选子网,例如)
  • @mrod 大约 12 年前我从事过一个审计项目,我认为(正如我所提到的)我们使用 Perl 或 C 来创建 UDP 包而没有发送任何实际包并读取包的源地址。并且给定一台具有多个网络接口的机器,问题中使用的术语“真实 IP”可以说取决于目的地。否则这种方法将无济于事。
【解决方案3】:

修复它:

  1. 找到您的主机名。类型:hostname。例如,您发现您的主机名是mycomputer.xzy.com

  2. 将您的主机名放入您的主机文件中。 /etc/hosts 。比如

    10.50.16.136 mycomputer.xzy.com
    

【讨论】:

  • 这对我来说是“修复”它的奇怪方式:如果你的应用程序的主机 IP 发生变化,你就死定了..
【解决方案4】:

这是一种避免 IPv6 和 Loopback 结果的方法。

public InetAddress getCurrentIp() {
            try {
                Enumeration<NetworkInterface> networkInterfaces = NetworkInterface
                        .getNetworkInterfaces();
                while (networkInterfaces.hasMoreElements()) {
                    NetworkInterface ni = (NetworkInterface) networkInterfaces
                            .nextElement();
                    Enumeration<InetAddress> nias = ni.getInetAddresses();
                    while(nias.hasMoreElements()) {
                        InetAddress ia= (InetAddress) nias.nextElement();
                        if (!ia.isLinkLocalAddress() 
                         && !ia.isLoopbackAddress()
                         && ia instanceof Inet4Address) {
                            return ia;
                        }
                    }
                }
            } catch (SocketException e) {
                LOG.error("unable to get current IP " + e.getMessage(), e);
            }
            return null;
        }

【讨论】:

    【解决方案5】:

    我写了这段代码:

    import java.net.InterfaceAddress;
    import java.net.NetworkInterface;
    import java.util.Collections;
    import java.util.HashSet;
    import java.util.Set;
    
    
    private String[] getHostAddresses() {
      Set<String> HostAddresses = new HashSet<>();
      try {
        for (NetworkInterface ni : Collections.list(NetworkInterface.getNetworkInterfaces())) {
          if (!ni.isLoopback() && ni.isUp() && ni.getHardwareAddress() != null) {
            for (InterfaceAddress ia : ni.getInterfaceAddresses()) {
              if (ia.getBroadcast() != null) {  //If limited to IPV4
                HostAddresses.add(ia.getAddress().getHostAddress());
              }
            }
          }
        }
      } catch (SocketException e) { }
      return HostAddresses.toArray(new String[0]);
    }
    

    检查一下!

    对我来说:

    • 不能是 LoopBack!
    • 必须启动!
    • 必须有 MAC 地址(不为空)

    【讨论】:

      【解决方案6】:

      您的计算机可能有多个 IP。你怎么知道是哪一个?我这样做的方法是在另一台机器上运行一个非常简单的 CGI,它会报告它所看到的 IP,当我需要知道我的 IP 在外界看来是什么样子时,我会点击它。

      【讨论】:

        【解决方案7】:

        我没有使用 InetAddress.getHostAddress(),而是调用我编写的 getHost4Address 例程来获取第一个非环回地址...

        /**
         * Returns this host's non-loopback IPv4 addresses.
         * 
         * @return
         * @throws SocketException 
         */
        private static List<Inet4Address> getInet4Addresses() throws SocketException {
            List<Inet4Address> ret = new ArrayList<Inet4Address>();
        
            Enumeration<NetworkInterface> nets = NetworkInterface.getNetworkInterfaces();
            for (NetworkInterface netint : Collections.list(nets)) {
                Enumeration<InetAddress> inetAddresses = netint.getInetAddresses();
                for (InetAddress inetAddress : Collections.list(inetAddresses)) {
                    if (inetAddress instanceof Inet4Address && !inetAddress.isLoopbackAddress()) {
                        ret.add((Inet4Address)inetAddress);
                    }
                }
            }
        
            return ret;
        }
        
        /**
         * Returns this host's first non-loopback IPv4 address string in textual
         * representation.
         * 
         * @return
         * @throws SocketException
         */
        private static String getHost4Address() throws SocketException {
            List<Inet4Address> inet4 = getInet4Addresses();
            return !inet4.isEmpty()
                    ? inet4.get(0).getHostAddress()
                    : null;
        }
        

        【讨论】:

          【解决方案8】:

          从当前实例获取当前请求

          HttpServletRequest httpServletRequest = (HttpServletRequest) FacesContext.getCurrentInstance().getExternalContext().getRequest();
          

          然后从请求中获取地址

          ip = httpServletRequest.getRemoteAddr();
          

          【讨论】:

          • 包含关于代码/解决方案的简介将使这个答案成为一个完整的答案!
          • 这个答案感觉是正确的。我正在寻找对我的服务器的 smpp 请求的客户端请求地址
          • FacesContext 不是 JDK 的一部分,它是 JSF 实现的一部分。 OP 没有提到 JSF afaik。
          【解决方案9】:

          获取当前框匹配模式的ip地址:

          import java.io.*; 
          import java.util.*; 
          import java.util.regex.Pattern; 
          
          String ipPattern = "(192.1.200.)(\\d){1,3}";      //your organization pattern 
          try{ 
              Enumeration en = NetworkInterface.getNetworkInterfaces(); 
              while (en.hasMoreElements()) { 
                  NetworkInterface ni = (NetworkInterface) en.nextElement(); 
                  Enumeration ee = ni.getInetAddresses(); 
                  while (ee.hasMoreElements()) { 
                      InetAddress ia = (InetAddress) ee.nextElement(); 
                      String ip = ia.getHostAddress(); 
                      System.out.println("ip: '" + ip + "'\n"); 
                      boolean matched = Pattern.matches(ipPattern, ip); 
                      if (matched) { 
                          System.out.println("matched\n"); 
                      }
                  } 
              } 
          } 
          catch(Exception e){ } 
          

          结果:

          ip: 'fe80:0:0:0:510a:528b:7204:39d0%enp0s25'
          ip: '192.1.200.3'
          matched
          ip: '0:0:0:0:0:0:0:1%lo'
          ip: '127.0.0.1'
          

          【讨论】:

          • 这个答案被删除了,因为它只是一个代码,我通过添加一个标题来拯救它,使代码更加自我记录并显示结果。将来,如果答案只是代码,没有任何解释,那么它通常会被自动标记。
          • 如果我们改变组织怎么办?
          【解决方案10】:

          我遇到同样问题的最短解决方案

          搜索后发现PCHsotName在"/etc/hosts"文件中得到了127.0.1.1 IP地址

          1) 所以使用任何编辑器打开文件 /etc/hosts

          我用过纳米

          $ sudo nano /etc/hosts
          

          2) 并在行首添加“#”

          127.0.1.1 HostName
          

          喜欢

          #127.0.1.1 HostName
          

          3) ctrl+o 保存

          4) ctrl+x 退出 nano 编辑器

          注意:“主机名”取决于您的计算机或服务器的名称。

          【讨论】:

            【解决方案11】:

            如果你想获得你电脑的IP地址,你必须使用“java.net.InetAddress”库中的“InetAddress”对象。

            以下方法返回你的IP:

            public String getIp() {
            
                String myIp = "";
                InetAddress ip;
            
                try {
                    ip = InetAddress.getLocalHost();
                    myIp = ip.getHostAddress();      // This method returns the IP.
                } catch (UnknownHostException e) {
                    e.printStackTrace();
                }
            
                return myIp;
            }
            

            【讨论】:

            • 此代码可能返回环回地址(如果 hosts 未修改)
            • 原问题说如何避免环回地址,这段代码会返回相同的。
            猜你喜欢
            • 1970-01-01
            • 2019-09-10
            • 2012-02-26
            • 2013-03-28
            • 2011-05-29
            • 2013-08-31
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多