使用Java如何获取客户端的局域网IP?

8

如何使用Java获取计算机的局域网IP地址?我想要与路由器和其他网络连接的IP地址。

我尝试了以下代码:

Socket s = new Socket("www.google.com", 80);
String ip = s.getLocalAddress().getHostAddress();
s.close();

这似乎在某些情况下有效,但有时会返回环回地址或完全不同的内容。此外,它需要互联网连接。

有人有更准确的方法吗?

编辑:认为在这里提问比在评论中更好。

如果您有许多接口怎么办?例如,一个用于电缆,一个用于wifi,一个用于虚拟盒子等。是否不可能实际上看到哪一个连接到网络?

5个回答

16

尝试使用java.net.NetworkInterface

import java.net.NetworkInterface;

...

for (
    final Enumeration< NetworkInterface > interfaces =
        NetworkInterface.getNetworkInterfaces( );
    interfaces.hasMoreElements( );
)
{
    final NetworkInterface cur = interfaces.nextElement( );

    if ( cur.isLoopback( ) )
    {
        continue;
    }

    System.out.println( "interface " + cur.getName( ) );

    for ( final InterfaceAddress addr : cur.getInterfaceAddresses( ) )
    {
        final InetAddress inet_addr = addr.getAddress( );

        if ( !( inet_addr instanceof Inet4Address ) )
        {
            continue;
        }

        System.out.println(
            "  address: " + inet_addr.getHostAddress( ) +
            "/" + addr.getNetworkPrefixLength( )
        );

        System.out.println(
            "  broadcast address: " +
                addr.getBroadcast( ).getHostAddress( )
        );
    }
}

如果你有很多接口怎么办?例如,一个用于电缆,一个用于WiFi,还有一个用于虚拟机等。你是否无法真正看到哪个接口连接到了网络? - cragiz
@Henrik。 在这种情况下,它们都是“连接”的。它取决于您的操作系统确定哪个将用于外部路由。您可以使用此Socket构造函数http://java.sun.com/j2se/1.5.0/docs/api/java/net/Socket.html#Socket(java.net.InetAddress,%20int,%20java.net.InetAddress,%20int)选择特定的本地地址和端口,或构造默认套接字并将其绑定到特定的接口。还要检查您是否可以从NetworkInterface对象中确定所需的信息。 - Alexander Pogrebnyak
1
@Henrik。另外,由于Java必须适用于所有操作系统,因此您可以编写一个小的shell脚本来确定哪个本地接口是“路由”接口,并将此信息传递给您的Java程序,以便它可以绑定到该特定接口。另一方面,当您连接Socket时,这项工作已经为您完成,因此我建议您仅在具有非常特定的要求时才执行此操作。从您的帖子中不清楚这些要求是什么。 - Alexander Pogrebnyak

7
起初:没有单一的地址。您的机器至少有两个地址(“lo”上的127.0.0.1和可能在“eth1”上的192.168.1.1)。
您想要这个:列出网络接口
正如您所预期的那样,您不能自动检测哪一个连接到您的任何路由器,因为这需要潜在地解析您的路由表。但是,如果您只想要任何非本地地址,这应该就足够了。为了确保,请在Vista或Windows 7上至少使用一次,因为它们添加了IPv6地址。
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

1

这是我使用了一段时间的方法。它包括一个小技巧来确定外部可见的IP地址。

private List<String> getLocalHostAddresses() {

    List<String> addresses = new ArrayList<String>();

    try {
        Enumeration<NetworkInterface> e = NetworkInterface.getNetworkInterfaces();

        while (e.hasMoreElements()) {
            NetworkInterface ni = e.nextElement();
            Enumeration<InetAddress> e2 = ni.getInetAddresses();
            while (e2.hasMoreElements())
                addresses.add(e2.nextElement().getHostAddress());
        }
        URL u = new URL("http://whatismyip.org");
        BufferedReader in = new BufferedReader(new InputStreamReader(
                u.openStream()));
        addresses.add(in.readLine());
        in.close();
    } catch (Exception ignore) {
    }

    return addresses;
}

0
try {
    InetAddress addr = InetAddress.getLocalHost();

    // Get IP Address
    byte[] ipAddr = addr.getAddress();

    // Get hostname
    String hostname = addr.getHostName();
} catch (UnknownHostException e) {
}

这将在许多机器上返回“127.0.0.1”,因此不是有效的答案。 - Afonso Lage

0
正如丹尼尔所指出的那样,您无法知道哪个接口是“连接”的。例如,如果计算机有多个网络接口卡,它们都连接到单独的物理局域网,该怎么办?
根据您的用例让用户决定使用哪个接口或尝试它们所有的接口。

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