使用Java获取当前计算机的IP地址

问题

我正在尝试开发一个系统,其中有不同的节点在不同的系统上或在同一系统上的不同端口上运行。

现在所有节点都创建一个Socket,其目标IP作为称为自举节点的特殊节点的IP。然后节点创建自己的ServerSocket并开始侦听连接。

引导节点维护一个节点列表,并在被查询时返回它们。

现在我需要的是节点必须将其IP注册到自举节点。我尝试使用cli.getInetAddress(),因为客户端连接到引导节点的ServerSocket,但这不起作用。

  • 我需要客户端注册其PPP IP(如果可用);
  • 否则LAN IP(如果有);
  • 否则它必须注册127.0.0.1,假设它是同一台计算机。

使用代码:

System.out.println(Inet4Address.getLocalHost().getHostAddress());

要么

System.out.println(InetAddress.getLocalHost().getHostAddress());

我的PPP连接IP地址是:117.204.44.192,但上面的返回值为192.168.1.2
编辑
我使用以下代码:

Enumeration e = NetworkInterface.getNetworkInterfaces();
while(e.hasMoreElements())
{
    NetworkInterface n = (NetworkInterface) e.nextElement();
    Enumeration ee = n.getInetAddresses();
    while (ee.hasMoreElements())
    {
        InetAddress i = (InetAddress) ee.nextElement();
        System.out.println(i.getHostAddress());
    }
}

我能够获得所有与NetworkInterface相关的IP地址,但我如何区分它们呢?这是我得到的输出:

127.0.0.1
192.168.1.2
192.168.56.1
117.204.44.19

#1 热门回答(233 赞)

在最一般的情况下,这可能有点棘手。

从表面上看,InetAddress.getLocalHost()应该为你提供该主机的IP地址。问题是主机可能有很多网络接口,接口可能绑定到多个IP地址。最重要的是,并非所有IP地址都可以在你的计算机或LAN之外访问。例如,它们可以是虚拟网络设备的IP地址,专用网络IP地址等。

这意味着InetAddress.getLocalHost()返回的IP地址可能不适合使用。

你怎么处理这个?

  • 一种方法是使用NetworkInterface.getNetworkInterfaces()获取主机上的所有已知网络接口,然后迭代每个NI的地址。
  • 另一种方法是(以某种方式)获取主机的外部广告FQDN,并使用InetAddress.getByName()来查找主IP地址。 (但是你如何得到它,以及如何处理基于DNS的负载均衡器?)
  • 前一个版本的变体是从配置文件或命令行参数中获取首选FQDN。
  • 另一种变体是从配置文件或命令行参数中获取首选IP地址。

总之,InetAddress.getLocalHost()通常可以工作,但是你可能需要为在"复杂"网络环境中运行代码的情况提供替代方法。

我能够获得与所有网络接口相关的所有IP地址,但我如何区分它们?

  • 127.xxx.xxx.xxx范围内的任何地址都是"环回"地址。它只对"这个"主机可见。
  • 192.168.xxx.xxx范围内的任何地址都是私有(即本地站点)IP地址。这些保留在组织内使用。这同样适用于10.xxx.xxx.xxx地址,172.16.xxx.xxx到172.31.xxx.xxx。
  • 169.254.xxx.xxx范围内的地址是链路本地IP地址。这些保留用于单个网段。
  • 224.xxx.xxx.xxx到239.xxx.xxx.xxx范围内的地址是多播地址。
  • 地址255.255.255.255是广播地址。
  • 其他任何东西都应该是有效的公共点对点IPv4地址。

事实上,InetAddress API提供了测试环回,链接本地,站点本地,多播和广播地址的方法。你可以使用这些来排序你获得的哪个IP地址是最合适的。


#2 热门回答(49 赞)

这里发布的测试IP歧义解决方法代码来自https://issues.apache.org/jira/browse/JCS-40(InetAddress.getLocalHost()在Linux系统上不明确):

/**
 * Returns an <code>InetAddress</code> object encapsulating what is most likely the machine's LAN IP address.
 * <p/>
 * This method is intended for use as a replacement of JDK method <code>InetAddress.getLocalHost</code>, because
 * that method is ambiguous on Linux systems. Linux systems enumerate the loopback network interface the same
 * way as regular LAN network interfaces, but the JDK <code>InetAddress.getLocalHost</code> method does not
 * specify the algorithm used to select the address returned under such circumstances, and will often return the
 * loopback address, which is not valid for network communication. Details
 * <a href="http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4665037">here</a>.
 * <p/>
 * This method will scan all IP addresses on all network interfaces on the host machine to determine the IP address
 * most likely to be the machine's LAN address. If the machine has multiple IP addresses, this method will prefer
 * a site-local IP address (e.g. 192.168.x.x or 10.10.x.x, usually IPv4) if the machine has one (and will return the
 * first site-local address if the machine has more than one), but if the machine does not hold a site-local
 * address, this method will return simply the first non-loopback address found (IPv4 or IPv6).
 * <p/>
 * If this method cannot find a non-loopback address using this selection algorithm, it will fall back to
 * calling and returning the result of JDK method <code>InetAddress.getLocalHost</code>.
 * <p/>
 *
 * @throws UnknownHostException If the LAN address of the machine cannot be found.
 */
private static InetAddress getLocalHostLANAddress() throws UnknownHostException {
    try {
        InetAddress candidateAddress = null;
        // Iterate all NICs (network interface cards)...
        for (Enumeration ifaces = NetworkInterface.getNetworkInterfaces(); ifaces.hasMoreElements();) {
            NetworkInterface iface = (NetworkInterface) ifaces.nextElement();
            // Iterate all IP addresses assigned to each card...
            for (Enumeration inetAddrs = iface.getInetAddresses(); inetAddrs.hasMoreElements();) {
                InetAddress inetAddr = (InetAddress) inetAddrs.nextElement();
                if (!inetAddr.isLoopbackAddress()) {

                    if (inetAddr.isSiteLocalAddress()) {
                        // Found non-loopback site-local address. Return it immediately...
                        return inetAddr;
                    }
                    else if (candidateAddress == null) {
                        // Found non-loopback address, but not necessarily site-local.
                        // Store it as a candidate to be returned if site-local address is not subsequently found...
                        candidateAddress = inetAddr;
                        // Note that we don't repeatedly assign non-loopback non-site-local addresses as candidates,
                        // only the first. For subsequent iterations, candidate will be non-null.
                    }
                }
            }
        }
        if (candidateAddress != null) {
            // We did not find a site-local address, but we found some other non-loopback address.
            // Server might have a non-site-local address assigned to its NIC (or it might be running
            // IPv6 which deprecates the "site-local" concept).
            // Return this non-loopback candidate address...
            return candidateAddress;
        }
        // At this point, we did not find a non-loopback address.
        // Fall back to returning whatever InetAddress.getLocalHost() returns...
        InetAddress jdkSuppliedAddress = InetAddress.getLocalHost();
        if (jdkSuppliedAddress == null) {
            throw new UnknownHostException("The JDK InetAddress.getLocalHost() method unexpectedly returned null.");
        }
        return jdkSuppliedAddress;
    }
    catch (Exception e) {
        UnknownHostException unknownHostException = new UnknownHostException("Failed to determine LAN address: " + e);
        unknownHostException.initCause(e);
        throw unknownHostException;
    }
}

#3 热门回答(40 赞)

你可以使用java'sInetAddressclass来实现此目的。

InetAddress IP=InetAddress.getLocalHost();
System.out.println("IP of my system is := "+IP.getHostAddress());

我系统的输出= IP of my system is := 10.100.98.228

getHostAddress()returns

返回文本演示文稿中的IP地址字符串。

或者你也可以

InetAddress IP=InetAddress.getLocalHost();
System.out.println(IP.toString());

输出= IP of my system is := RanRag-PC/10.100.98.228