如何通过Java在Linux上获取计算机的IP?

12
如何通过Java在Linux上获取计算机的IP地址?
我搜索了一些例子,发现了与NetworkInterface类相关的内容,但我不知道如何获取IP地址。
如果同时运行多个网络接口会发生什么?哪个IP地址将被返回。
我真的很希望有一些代码示例。
附:我之前使用的InetAddress类对于跨平台应用程序是一个糟糕的解决方案(win / Linux)。

当您使用 InetAddress 时会发生什么? - karim79
这是一个完全重复的问题,我已经将参考链接编辑到了问题中。那里有很多答案。InetAddress非常适合跨平台使用,我从未遇到过任何问题。 - Eddie
1
如果您有多个网卡,并且要求获取计算机的“一个”IP地址,则所获得的IP地址取决于计算机上网络接口的绑定顺序,这取决于许多变量。我不会依赖它是可预测的。 - Eddie
6个回答

31

不要忘记回环地址,因为它们在外部是不可见的。这里有一个函数,可以提取第一个非回环IP地址(IPv4或IPv6)。

private static InetAddress getFirstNonLoopbackAddress(boolean preferIpv4, boolean preferIPv6) throws SocketException {
    Enumeration en = NetworkInterface.getNetworkInterfaces();
    while (en.hasMoreElements()) {
        NetworkInterface i = (NetworkInterface) en.nextElement();
        for (Enumeration en2 = i.getInetAddresses(); en2.hasMoreElements();) {
            InetAddress addr = (InetAddress) en2.nextElement();
            if (!addr.isLoopbackAddress()) {
                if (addr instanceof Inet4Address) {
                    if (preferIPv6) {
                        continue;
                    }
                    return addr;
                }
                if (addr instanceof Inet6Address) {
                    if (preferIpv4) {
                        continue;
                    }
                    return addr;
                }
            }
        }
    }
    return null;
}

13

参考Java教程

为什么InetAddress不是一个好的解决方案?我在文档中没有看到关于跨平台兼容性的任何内容?

此代码将枚举所有网络接口并检索它们的信息。

import java.io.*;
import java.net.*;
import java.util.*;
import static java.lang.System.out;

public class ListNets 
{
    public static void main(String args[]) throws SocketException {
        Enumeration<NetworkInterface> nets = NetworkInterface.getNetworkInterfaces();
        for (NetworkInterface netint : Collections.list(nets))
            displayInterfaceInformation(netint);
    }

    static void displayInterfaceInformation(NetworkInterface netint) throws SocketException {
        out.printf("Display name: %s\n", netint.getDisplayName());
        out.printf("Name: %s\n", netint.getName());
        Enumeration<InetAddress> inetAddresses = netint.getInetAddresses();
        for (InetAddress inetAddress : Collections.list(inetAddresses)) {
            out.printf("InetAddress: %s\n", inetAddress);
        }
        out.printf("\n");
     }
}  
以下是示例程序的输出结果:
Display name: bge0
Name: bge0
InetAddress: /fe80:0:0:0:203:baff:fef2:e99d%2
InetAddress: /121.153.225.59

Display name: lo0
Name: lo0
InetAddress: /0:0:0:0:0:0:0:1%1
InetAddress: /127.0.0.1


3
回答“为什么InetAddress不是一个好的解决方案?”:在Linux系统中,如果主机名列在/etc/hosts中的127.0.0.1中,则结果不是非常有用。在主机名既未出现在/etc/hosts又未出现在DNS中的系统上,您将获得UnknownHostException。在OS X上,主机名似乎通常能够很好地解析。我不知道Windows的情况,但我想它足够好用。 - Jeremy Huiskamp
以上代码无法运行,请从此处复制并粘贴:https://gist.github.com/1225358 - user285594

5
这段代码对我有效:
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.util.Enumeration;


public class ShowIp {

    public static void main(String[] args) throws SocketException {
        NetworkInterface ni = NetworkInterface.getByName("eth0");
        Enumeration<InetAddress> inetAddresses =  ni.getInetAddresses();


        while(inetAddresses.hasMoreElements()) {
            InetAddress ia = inetAddresses.nextElement();
            if(!ia.isLinkLocalAddress()) {
                System.out.println("IP: " + ia.getHostAddress());
            }
        }
    }

}

4

仅返回第一个非环回接口可能不可行,因为它可能是由某些软件(如Parallels)创建的。更好的方法是尝试寻找eth0接口。

static private InetAddress getIPv4InetAddress() throws SocketException, UnknownHostException {

    String os = System.getProperty("os.name").toLowerCase();

    if(os.indexOf("nix") >= 0 || os.indexOf("nux") >= 0) {   
        NetworkInterface ni = NetworkInterface.getByName("eth0");

        Enumeration<InetAddress> ias = ni.getInetAddresses();

        InetAddress iaddress;
        do {
            iaddress = ias.nextElement();
        } while(!(iaddress instanceof Inet4Address));

        return iaddress;
    }

    return InetAddress.getLocalHost();  // for Windows and OS X it should work well
}

我尝试了你的代码,但没有返回我的实际IP地址。我的电脑安装了虚拟主机,它返回给我其中一个虚拟主机的IP地址。我也尝试了@adrian.tarau提供的解决方案,结果非常好用,真正地返回了我的本地机器IP地址。 - Sagar G.

0
我找到的最佳解决方案是在Linux / Ubuntu机器上运行命令。 因此,我使用Java运行此命令hostname -I | cut -d' ' -f1
请注意-方法的第二部分只是为了收集输出。
public String getIP() throws IOException
{
    ProcessBuilder pb = new ProcessBuilder("bash", "-c", "hostname -I | cut -d' ' -f1");

    Process process = pb.start();
    InputStream inputStream = process.getInputStream();
    Scanner scanner = new Scanner(inputStream, StandardCharsets.UTF_8);

    StringBuilder outputString = new StringBuilder();
    while (scanner.hasNextLine())
    {
        synchronized (this)
        {
            String message = scanner.nextLine();
            outputString.append(message);
            outputString.append("\n");
            log(message);
        }
    }
    scanner.close();

    return outputString.toString().trim();
}

0
在我的情况下,最简单的解决方案是使用Socket.getLocalAddress()。我必须专门为此打开Socket,但在我的Ubuntu 10.04机器上,由于有多个NetworkInterfaces,这是获取外部IP地址的唯一方法。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接