【问题标题】:Finding local machine IP address without false positives查找没有误报的本地机器 IP 地址
【发布时间】:2018-05-16 09:56:41
【问题描述】:

我尝试使用 Java 查找我的 PC 的本地 IP 地址。然而,结果并不正确。具体来说,我需要来自ipconfig 命令的无线局域网适配器WiFi IPv4 地址。我查看了许多不同的问题,例如this excellent answer,但不清楚如何在 Java 中做到这一点。 InetAddress.getLocalHost() 返回错误的 IP('Ethernet-Adapter VirtualBox Host-Only Network')。

我尝试了以下代码:

public static List<String> getLocalIPAddresses() throws Exception
{
    val networkInterfaces = NetworkInterface.getNetworkInterfaces();
    val localIPAddresses = new ArrayList<String>();

    while (networkInterfaces.hasMoreElements())
    {
        for (val interfaceAddress : networkInterfaces.nextElement().getInterfaceAddresses())
        {
            val address = interfaceAddress.getAddress();

            // Find the local IP addresses
            if (address.isSiteLocalAddress())
            {
                val localIPAddress = interfaceAddress.getAddress().toString().replace("/", "");
                localIPAddresses.add(localIPAddress);
            }
        }
    }

    if (localIPAddresses.isEmpty())
    {
        throw new IllegalStateException("Expected the computer's local IP address but didn't get one!");
    }

    return localIPAddresses;
}

注意:
val 来自Lombok

在我的机器上,这会返回一个包含 2 个 IP 地址的列表:

192.168.56.1
192.168.2.103

“以太网适配器 VirtualBox 仅主机网络”一个和正确的“无线 LAN 适配器 WiFi”一个。我能做些什么来始终保证后者?显然检查 isSiteLocalAddress()(又名本地 IP 地址)是不够的。代码方面还能做什么?过滤掉“VirtualBox”并不是万无一失的解决方案,尤其是因为网络接口名称取决于语言:

public static List<String> getLocalIPAddresses() throws Exception
{
    val networkInterfaces = NetworkInterface.getNetworkInterfaces();
    val localIPAddresses = new ArrayList<String>();

    while (networkInterfaces.hasMoreElements())
    {
        val networkInterface = networkInterfaces.nextElement();
        val displayName = networkInterface.getDisplayName();

        if (!displayName.contains("VirtualBox"))
        {
            for (val interfaceAddress : networkInterface.getInterfaceAddresses())
            {
                val address = interfaceAddress.getAddress();

                // Find the local IP addresses
                if (address.isSiteLocalAddress())
                {
                    val localIPAddress = interfaceAddress.getAddress().toString().replace("/", "");
                    localIPAddresses.add(localIPAddress);
                }
            }
        }
    }

    if (localIPAddresses.isEmpty())
    {
        throw new IllegalStateException("Expected the computer's local IP address but didn't get one!");
    }

    return localIPAddresses;
}

我需要一个独立于平台的解决方案。不过我在 Windows 上。

【问题讨论】:

  • 是否在同一个网络接口上找到了两个 IP?如果不是,你能用networkIntreface.isVirtual()等布尔测试来区分接口吗?
  • @MichaelMcKay:即使在包含isVirtual() 检查代码后仍然返回 2 个 IP。它们各自位于不同的网络接口上。
  • 如果“InetAddress.getLocalHost() 返回错误的 IP”,你能用它在你的 for 循环中过滤掉它吗?
  • @MichaelMcKay:不,因为对于另一台机器它可能是正确的......
  • 我唯一可以建议的另一件事是使用 getName() 方法并选择第一个以“wlan”开头的方法。最后,这两个 IP 地址都是对“我的 IP 地址是什么?”问题的有效答案。 - 不是误报。您可以使用 Windows 中的主机文件来指定选择哪个作为默认值,但该文件可能在许多计算机上不存在。您还可以查看命名服务。

标签: java networking ip ipv4


【解决方案1】:

你为什么不使用isVirtual()方法。

static List<String> getLocalIpAddress() throws SocketException {
    Enumeration<NetworkInterface> networkInterfaces = null;
    List<String> localIpAddress = new ArrayList<String>();

    networkInterfaces = NetworkInterface.getNetworkInterfaces();

    while (networkInterfaces.hasMoreElements()) {
        NetworkInterface ni = networkInterfaces.nextElement();
        System.out.println("=== <" + ni.getDisplayName() + "> ===");

        if (!ni.isUp()) {
            for (InterfaceAddress addr : ni.getInterfaceAddresses()) {
                System.out.println("not up : " + addr.getAddress().getHostAddress());
            }
            continue;
        }
        if (ni.isLoopback()) {
            for (InterfaceAddress addr : ni.getInterfaceAddresses()) {
                System.out.println("loopback : " + addr.getAddress().getHostAddress());
            }
            continue;
        }
        if (ni.isVirtual()) {
            for (InterfaceAddress addr : ni.getInterfaceAddresses()) {
                System.out.println("virtual : " + addr.getAddress().getHostAddress());
            }
            continue;
        }

        if (!ni.isPointToPoint()) {
            for (InterfaceAddress addr : ni.getInterfaceAddresses()) {
                System.out.println("not ppp : " + addr.getAddress().getHostAddress());
            }
            continue;
        }

        for (InterfaceAddress addr : ni.getInterfaceAddresses()) {
            InetAddress address = addr.getAddress();
            if (address.isLinkLocalAddress()) {
                System.out.println("link local address: " + address.getHostName() + address.getHostAddress());
                continue;
            }
            if (address.isSiteLocalAddress()) {
                System.out.println("site local address: " + address.getHostName() + address.getHostAddress());
                continue;
            }

            System.out.println("getHostName: " + address.getHostName());
            System.out.println("getHostAddress : " + address.getHostAddress());
            System.out.println("------separator-------");

            localIpAddress.add(address.getHostAddress());
        }
    }

    return localIpAddress;
}

【讨论】:

  • 两个IP都打印为not ppp :,否则根本不打印。
猜你喜欢
  • 2011-07-02
  • 1970-01-01
  • 2021-08-20
  • 1970-01-01
  • 1970-01-01
  • 2015-12-06
  • 2016-01-21
  • 1970-01-01
相关资源
最近更新 更多