从Java applet获取正确的本地IP地址

9

我希望从我的Java小程序中确定本地IP地址。问题在于当同一台机器有局域网和互联网连接(例如palm,VMWare等)时,会有多个IP地址。

以下是我的测试:

    public static void main(String[] args) {
      try {
        String hostName = InetAddress.getLocalHost().getHostName();
        System.out.println("HostName = " + hostName);
        System.out.println("HostAddressLocal = " +
          InetAddress.getLocalHost().getHostAddress());
        InetAddress[] inetAddresses = InetAddress.getAllByName(hostName);
        for (InetAddress inetAddress : inetAddresses) {
          System.out.println("hostAddress = " + inetAddress.getHostAddress());
        }
      } catch (Exception e) {
          e.printStackTrace();
      }
    }

结果是:
    HostName = xxxx
    HostAddressLocal = xx.xx.xx.xx
    hostAddress = 10.10.11.51
    hostAddress = 192.168.23.1
    hostAddress = 192.168.106.1

xx.xx.xx.xx不是正确的地址,正确的是10.10.11.51。


针对jarnbjo的回复进行编辑:

你的预测准确。你理解了我的问题。客户端可以通过代理连接,因此我不能使用你提供的第一种方法。如果我在我的电脑上执行以下代码:

    Socket s = new Socket("www.w3c.org", 80); 
    InetAddress ip = s.getLocalAddress(); 
    System.out.println("Internet IP = " + ip.toString()); 
    s.close(); 

我有这个结果:
    Internet IP = /127.0.0.1 

而不是10.10.11.51


你指的是小程序吗?有一个主函数并能够访问本地UP地址? - Tom Hawtin - tackline
我们也遇到了那个问题。 - KLE
3
你到底想做什么?你为什么需要这些信息?如果用户没有本地地址怎么办?如果用户有多个接口和多个本地地址怎么办?如果用户使用IPv6(每个接口可能会有多个地址),该怎么办?你的程序存在一些设计问题,不应该依赖这些特征来正确运行。 - Juliano
同样的问题在这里,感谢帖子 ;) - reef
2个回答

11

如您已经发现,一台计算机可能拥有多个具有不同IP地址的网络接口,因此很难猜测您认为哪一个是“正确”的,实际上它们都是正确的。

据我所知,您想要获取客户端用于连接到服务器并从中加载小程序的IP地址。如果是这样,您至少有两种可能性:

  • 在服务器上,您可以将小程序嵌入动态生成的HTML页面中,并将客户端的IP地址作为小程序参数添加进去。至少在没有使用代理进行HTTP时,Web服务器应该能够确定客户端的IP地址并将其传递给小程序。

  • 在小程序中,您可以打开到从中加载小程序的Web服务器的TCP套接字并检查用于连接的本地地址是哪个。

.

Socket s = new Socket("www", 80);
InetAddress ip = s.getLocalAddress();
s.close();

由于默认沙盒模式中缺乏安全权限,这通常在 applet 中无法正常工作。您将需要在 applet 的策略文件中授予 java.net.NetPermission.getNetworkInformation 权限给 applet。 - Jason C
创建用于“www”的套接字已停止工作,请参见我的问题:http://stackoverflow.com/questions/28487579/jsp-new-socket-www-80-stopped-working-after-years-of-working-ok - Tulains Córdova

-1
在getHostName() C函数的底部,它首先查找/etc/hosts,然后尝试通过DNS解析。因此,如果您将10.10.11.51 myhostname添加到/etc/hosts中,则getHostName()应该正确检测到它。
在Windows中,有类似于/etc/hosts的东西,在\WINDOWS\System32\Servises或其他地方...
这只是名称解析问题。
在您的代码中,您首先获取主机名(hostName = InetAddress.getLocalHost().getHostName();),该函数返回安装系统时设置的计算机名称。然后,您获取具体主机名的所有IP地址(InetAddress.getAllByName(hostName)) - 这将返回为此主机名解析的所有IP地址。
简单的例子:
1 /etc/hosts如下所示
127.0.0.1 localhost 127.0.1.1 fred-desktop 您的代码返回
HostName = fred-desktop HostAddressLocal = 127.0.1.1 hostAddress = 127.0.1.1
2 将/etc/hosts更改为以下内容
127.0.0.1   localhost
127.0.1.1   fred-desktop
192.168.1.1 fred-desktop
20.20.20.20 fred-desktop

你的代码将返回

主机名 = fred-desktop
本地主机地址 = 127.0.1.1
主机地址 = 127.0.1.1
主机地址 = 192.168.1.1
主机地址 = 20.20.20.20

fred-desktop - 我的 Ubuntu 电脑名称。


那不是问题所在。问题不在于名称解析,而在于可能存在多个接口。 - sleske
这个问题是关于Java的,而你却给出了一个用于不同目的的C语言调用。 - mmmmmm
1
@mark - 你完全不理解我在说什么... InetAddress.getAllByName(hostName) - 返回主机名的IP地址,而不是通过此主机的PHISICAL接口。这不是获取本地机器接口的正确方法。 - Alexey Sviridov

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