java InetAddress.getLocalHost();返回 127.0.0.1 ...如何获得真实 IP?

Posted

技术标签:

【中文标题】java InetAddress.getLocalHost();返回 127.0.0.1 ...如何获得真实 IP?【英文标题】:java InetAddress.getLocalHost(); returns 127.0.0.1 ... how to get REAL 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”)。 【参考方案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】:

修复它:

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

    将您的主机名放入您的主机文件中。 /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 未修改) 原问题说如何避免环回地址,这段代码会返回相同的。

以上是关于java InetAddress.getLocalHost();返回 127.0.0.1 ...如何获得真实 IP?的主要内容,如果未能解决你的问题,请参考以下文章

Java 布尔运算

java [Java] Java常用代码#java

Java - 35 Java 实例

Java While 循环

Java 字符串

Java If ... Else