ChatGPT解决这个技术问题 Extra ChatGPT

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

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

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

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

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

如果可用,我需要客户端注册其 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
Inet4Address.getLocalHost() 应该可以正常工作吗?
如果我添加 n.isPointToPoint() 在循环内部会起作用吗?如果没有找到点对点网络,我的想法是返回“127.0.0.1”。这行得通吗??
@sasidhar:请不要发布您的真实 IP 地址。写 117.xxx.xxx.xxx,私网 IP 没关系。
@GagandeepBali 感谢您的建议,但我的 IP 是动态 IP,每次断开连接并连接互联网时,我都会获得一个新 IP。所以应该不是问题,我想。

S
Stephen C

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

从表面上看,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 地址是最合适的。


如果有人好奇,getLocalHost 本质上是对服务器的主机名进行 DNS 查找。如果它从该查找中获得 IP 地址,则它会搜索可用的接口以查看哪个接口具有该 IP 地址并返回该接口。这意味着 getLocalHost 将倾向于在“服务器”环境中工作,其中传出 IP 是映射到服务器主机名的那个。
在 Ubuntu 14.04 上,这个 api 返回 127.0.1.1,即使 ifconfig 只报告两个接口,一个是我想要的(可公开访问的 IP 地址),另一个是环回(127.0.0.1)。奇怪的是它返回一个不同的环回别名。
我要补充一点,如果您 use getLocalHost().getHostAddress() 发布某些内容,您可能会在网络上的另一台计算机上看到 0.0.0.0。这是解释 here 这就是我在两台计算机上使用 Gazebo 时发生的事情
H
Hector
import java.net.DatagramSocket;
import java.net.InetAddress;

try(final DatagramSocket socket = new DatagramSocket()){
  socket.connect(InetAddress.getByName("8.8.8.8"), 10002);
  ip = socket.getLocalAddress().getHostAddress();
}

当有多个网络接口时,这种方式效果很好。它总是返回首选的出站 IP。目的地 8.8.8.8 不需要可到达。

Connect 在 UDP 套接字上具有以下效果:它设置发送/接收的目标,丢弃来自其他地址的所有数据包,并且 - 这就是我们使用的 - 将套接字转换为“连接”状态,设置其适当的字段。这包括根据系统的路由表检查到目的地的路由是否存在,并相应地设置本地端点。最后一部分似乎没有正式记录,但它看起来像是 Berkeley 套接字 API 的一个整体特征(UDP“连接”状态的副作用),它可以在 Windows 和 Linux 中跨版本和发行版可靠地工作。

因此,此方法将提供用于连接到指定远程主机的本地地址。没有建立真正的连接,因此指定的远程 ip 可能无法访问。

编辑:

正如 @macomgil 所说,对于 MacOS,您可以这样做:

Socket socket = new Socket();
socket.connect(new InetSocketAddress("google.com", 80));
System.out.println(socket.getLocalAddress());

它在 linux 上对我有用,但在 OsX 上我得到:“0.0.0.0”
@Jeef,答案已更新。如果它在 OsX 上不起作用,那么您需要选择另一种方式。
杰出的!仅供参考,在处理封闭的内部网络时,只需将 8.8.8.8 替换为每个主机都可以访问的东西
在 Windows 上工作;我们可以确认 OSX 是否仍然存在问题?
@trilogy 我仍然在 OSX 上获得 0.0.0.0
V
Vadzim

在此处发布测试来自 https://issues.apache.org/jira/browse/JCS-40 的 IP 模糊解决方法代码(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;
    }
}

必须注意的是,如果主机有多个相似的神经网络接口,这仍然不能解决歧义。
下面的答案更好 - stackoverflow.com/questions/9481865/… 获取用作默认网关的 src 的本地 IP 地址
为什么IP地址加上前斜线..?像/10.39.0.17 ..?,是否总是应该修剪这种方式..?
R
RanRag

为此,您可以使用 java 的 InetAddress 类。

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

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

getHostAddress() 返回

以文本形式返回 IP 地址字符串。

或者你也可以这样做

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

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


请注意,10.xxx 是私有地址,表示您的系统在 NAT 网络上。与外界联系时,它会显示为不同的地址。如果您确实需要外部 IP 地址,则必须联系许多站点之一,这些站点将向您回显您来自的 IP 地址。这可能对你有用,也可能没用。无论如何,您的系统几乎肯定无法从外部访问。
天哪,这是救我的命。以前我使用 clientSocket.getInetAddress().getHostName();
此解决方案不适用于 Linux 系统。
a
a problem solver

当你在寻找你的“本地”地址时,你应该注意每台机器不仅有一个网络接口,而且每个接口都可以有自己的本地地址。这意味着您的机器始终拥有多个“本地”地址。

当您连接到不同的端点时,将自动选择使用不同的“本地”地址。例如,当您连接到 google.com 时,您使用的是“外部”本地地址;但是当您连接到 localhost 时,您的本地地址始终是 localhost 本身,因为 localhost 只是一个环回。

下面展示了如何在与 google.com 通信时找到您的本地地址:

Socket socket = new Socket();
socket.connect(new InetSocketAddress("google.com", 80));
System.out.println(socket.getLocalAddress());
socket.close();

惊人的 !! - 太简单 :)
在末尾添加 socket.close() :)
A
Andrzej Jozwik

scala 中的示例(在 sbt 文件中有用):

  import collection.JavaConverters._
  import java.net._

  def getIpAddress: String = {

    val enumeration = NetworkInterface.getNetworkInterfaces.asScala.toSeq

    val ipAddresses = enumeration.flatMap(p =>
      p.getInetAddresses.asScala.toSeq
    )

    val address = ipAddresses.find { address =>
      val host = address.getHostAddress
      host.contains(".") && !address.isLoopbackAddress
    }.getOrElse(InetAddress.getLocalHost)

    address.getHostAddress
  }

n
nIcE cOw

编辑 1:更新的代码,因为上一个链接,不再存在

import java.io.*;
import java.net.*;

public class GetMyIP {
    public static void main(String[] args) {
        URL url = null;
        BufferedReader in = null;
        String ipAddress = "";
        try {
            url = new URL("http://bot.whatismyipaddress.com");
            in = new BufferedReader(new InputStreamReader(url.openStream()));
            ipAddress = in.readLine().trim();
            /* IF not connected to internet, then
             * the above code will return one empty
             * String, we can check it's length and
             * if length is not greater than zero, 
             * then we can go for LAN IP or Local IP
             * or PRIVATE IP
             */
            if (!(ipAddress.length() > 0)) {
                try {
                    InetAddress ip = InetAddress.getLocalHost();
                    System.out.println((ip.getHostAddress()).trim());
                    ipAddress = (ip.getHostAddress()).trim();
                } catch(Exception exp) {
                    ipAddress = "ERROR";
                }
            }
        } catch (Exception ex) {
            // This try will give the Private IP of the Host.
            try {
                InetAddress ip = InetAddress.getLocalHost();
                System.out.println((ip.getHostAddress()).trim());
                ipAddress = (ip.getHostAddress()).trim();
            } catch(Exception exp) {
                ipAddress = "ERROR";
            }
            //ex.printStackTrace();
        }
        System.out.println("IP Address: " + ipAddress);
    }
}

实际版本:这停止工作

希望这个片段可以帮助您实现这一目标:

// Method to get the IP Address of the Host.
private String getIP()
{
    // This try will give the Public IP Address of the Host.
    try
    {
        URL url = new URL("http://automation.whatismyip.com/n09230945.asp");
        BufferedReader in = new BufferedReader(new InputStreamReader(url.openStream()));
        String ipAddress = new String();
        ipAddress = (in.readLine()).trim();
        /* IF not connected to internet, then
         * the above code will return one empty
         * String, we can check it's length and
         * if length is not greater than zero, 
         * then we can go for LAN IP or Local IP
         * or PRIVATE IP
         */
        if (!(ipAddress.length() > 0))
        {
            try
            {
                InetAddress ip = InetAddress.getLocalHost();
                System.out.println((ip.getHostAddress()).trim());
                return ((ip.getHostAddress()).trim());
            }
            catch(Exception ex)
            {
                return "ERROR";
            }
        }
        System.out.println("IP Address is : " + ipAddress);

        return (ipAddress);
    }
    catch(Exception e)
    {
        // This try will give the Private IP of the Host.
        try
        {
            InetAddress ip = InetAddress.getLocalHost();
            System.out.println((ip.getHostAddress()).trim());
            return ((ip.getHostAddress()).trim());
        }
        catch(Exception ex)
        {
            return "ERROR";
        }
    }
}

如果我总是连接到互联网,希望该解决方案会起作用,但我不能保证。此外,当系统没有连接到互联网时,如果有,我需要返回系统的局域网 IP 地址,否则返回 localhost。所以对我来说不是一个可行的选择。还有什么办法??
@sasidhar:当你连接到互联网时,我猜只有你有你的公共 IP,如果你没有连接,那么这个方法会给你,你的本地 IP 或 LAN IP,以及你指定的最后一个条件您可以返回“127.0.0.1”,而不是返回错误。
我喜欢你的方法,但那个链接似乎不再起作用了!!我可以在我自己的系统上放置一个控制器来代替那个外部链接来工作,这样更可靠吗???
@Bludream:非常感谢您告诉我这个链接不再起作用。我已经更新了帖子,并添加了一些新的输入。希望它适用于您的用户案例。关于您的问题,我真的不知道如何在您自己的系统上设置控制器以使其工作。所以我无法就这个话题发表见解,我的坏。再次感谢并保持微笑:-)
尽管这是一个很酷的解决方案,但它非常不可靠。如果您要阻塞主线程(比如说)并且由于某种原因 whatismyip.com 关闭了一段时间,您的应用程序也会关闭:(。或者它会返回垃圾数据并导致意外行为。此外,这返回 whatismyip.com 可检测到的最外层 IP 地址,不一定是您正在使用的机器的 IP 地址。
J
J.R
private static InetAddress getLocalAddress(){
        try {
            Enumeration<NetworkInterface> b = NetworkInterface.getNetworkInterfaces();
            while( b.hasMoreElements()){
                for ( InterfaceAddress f : b.nextElement().getInterfaceAddresses())
                    if ( f.getAddress().isSiteLocalAddress())
                        return f.getAddress();
            }
        } catch (SocketException e) {
            e.printStackTrace();
        }
        return null;
    }

请考虑添加一些关于您的代码功能的解释。
G
Gautam

首先导入类

import java.net.InetAddress;

在班上

  InetAddress iAddress = InetAddress.getLocalHost();
  String currentIp = iAddress.getHostAddress();
  System.out.println("Current IP address : " +currentIp); //gives only host address

它只给出第一个 IP 地址,即使它不是正在使用的 IP 地址!
t
thSoft

您可以使用 java.net.InetAddress API。尝试这个 :

InetAddress.getLocalHost().getHostAddress();

它只会返回 127.0.0.1
多余的答案:stackoverflow.com/a/25257429/139985 说了同样的话。
D
Decoded

这是上面接受的答案的一个工作示例!此 NetIdentity 类将存储内部主机 ip 以及本地环回。如果您在基于 DNS 的服务器上,如上所述,您可能需要添加更多检查,或者可能转到配置文件路由。

import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.net.UnknownHostException;
import java.util.Enumeration;

/**
 * Class that allows a device to identify itself on the INTRANET.
 * 
 * @author Decoded4620 2016
 */
public class NetIdentity {

    private String loopbackHost = "";
    private String host = "";

    private String loopbackIp = "";
    private String ip = "";
    public NetIdentity(){

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

            while(interfaces.hasMoreElements()){
                NetworkInterface i = interfaces.nextElement();
                if(i != null){
                    Enumeration<InetAddress> addresses = i.getInetAddresses();
                    System.out.println(i.getDisplayName());
                    while(addresses.hasMoreElements()){
                        InetAddress address = addresses.nextElement();
                        String hostAddr = address.getHostAddress();

                        // local loopback
                        if(hostAddr.indexOf("127.") == 0 ){
                            this.loopbackIp = address.getHostAddress();
                            this.loopbackHost = address.getHostName();
                        }

                        // internal ip addresses (behind this router)
                        if( hostAddr.indexOf("192.168") == 0 || 
                                hostAddr.indexOf("10.") == 0 || 
                                hostAddr.indexOf("172.16") == 0 ){
                            this.host = address.getHostName();
                            this.ip = address.getHostAddress();
                        }


                        System.out.println("\t\t-" + address.getHostName() + ":" + address.getHostAddress() + " - "+ address.getAddress());
                    }
                }
            }
        }
        catch(SocketException e){

        }
        try{
            InetAddress loopbackIpAddress = InetAddress.getLocalHost();
            this.loopbackIp = loopbackIpAddress.getHostName();
            System.out.println("LOCALHOST: " + loopbackIp);
        }
        catch(UnknownHostException e){
            System.err.println("ERR: " + e.toString());
        }
    }

    public String getLoopbackHost(){
        return loopbackHost;
    }

    public String getHost(){
        return host;
    }
    public String getIp(){
        return ip;
    }
    public String getLoopbackIp(){
        return loopbackIp;
    }
}

当我运行这段代码时,我实际上得到了这样的打印输出:

    Software Loopback Interface 1
        -127.0.0.1:127.0.0.1 - [B@19e1023e
        -0:0:0:0:0:0:0:1:0:0:0:0:0:0:0:1 - [B@7cef4e59
Broadcom 802.11ac Network Adapter
        -VIKING.yourisp.com:192.168.1.142 - [B@64b8f8f4
        -fe80:0:0:0:81fa:31d:21c9:85cd%wlan0:fe80:0:0:0:81fa:31d:21c9:85cd%wlan0 - [B@2db0f6b2
Microsoft Kernel Debug Network Adapter
Intel Edison USB RNDIS Device
Driver for user-mode network applications
Cisco Systems VPN Adapter for 64-bit Windows
VirtualBox Host-Only Ethernet Adapter
        -VIKING:192.168.56.1 - [B@3cd1f1c8
        -VIKING:fe80:0:0:0:d599:3cf0:5462:cb7%eth4 - [B@3a4afd8d
LogMeIn Hamachi Virtual Ethernet Adapter
        -VIKING:25.113.118.39 - [B@1996cd68
        -VIKING:2620:9b:0:0:0:0:1971:7627 - [B@3339ad8e
        -VIKING:fe80:0:0:0:51bf:994d:4656:8486%eth5 - [B@555590
Bluetooth Device (Personal Area Network)
        -fe80:0:0:0:4c56:8009:2bca:e16b%eth6:fe80:0:0:0:4c56:8009:2bca:e16b%eth6 - [B@3c679bde
Bluetooth Device (RFCOMM Protocol TDI)
Intel(R) Ethernet Connection (2) I218-V
        -fe80:0:0:0:4093:d169:536c:7c7c%eth7:fe80:0:0:0:4093:d169:536c:7c7c%eth7 - [B@16b4a017
Microsoft Wi-Fi Direct Virtual Adapter
        -fe80:0:0:0:103e:cdf0:c0ac:1751%wlan1:fe80:0:0:0:103e:cdf0:c0ac:1751%wlan1 - [B@8807e25
VirtualBox Host-Only Ethernet Adapter-HHD Software NDIS 6.0 Filter Driver-0000
VirtualBox Host-Only Ethernet Adapter-WFP Native MAC Layer LightWeight Filter-0000
VirtualBox Host-Only Ethernet Adapter-HHD Software NDIS 6.0 Filter Driver-0001
VirtualBox Host-Only Ethernet Adapter-HHD Software NDIS 6.0 Filter Driver-0002
VirtualBox Host-Only Ethernet Adapter-VirtualBox NDIS Light-Weight Filter-0000
VirtualBox Host-Only Ethernet Adapter-HHD Software NDIS 6.0 Filter Driver-0003
VirtualBox Host-Only Ethernet Adapter-QoS Packet Scheduler-0000
VirtualBox Host-Only Ethernet Adapter-HHD Software NDIS 6.0 Filter Driver-0004
VirtualBox Host-Only Ethernet Adapter-WFP 802.3 MAC Layer LightWeight Filter-0000
VirtualBox Host-Only Ethernet Adapter-HHD Software NDIS 6.0 Filter Driver-0005
Intel(R) Ethernet Connection (2) I218-V-HHD Software NDIS 6.0 Filter Driver-0000
Intel(R) Ethernet Connection (2) I218-V-WFP Native MAC Layer LightWeight Filter-0000
Intel(R) Ethernet Connection (2) I218-V-HHD Software NDIS 6.0 Filter Driver-0001
Intel(R) Ethernet Connection (2) I218-V-Shrew Soft Lightweight Filter-0000
Intel(R) Ethernet Connection (2) I218-V-HHD Software NDIS 6.0 Filter Driver-0002
Intel(R) Ethernet Connection (2) I218-V-VirtualBox NDIS Light-Weight Filter-0000
Intel(R) Ethernet Connection (2) I218-V-HHD Software NDIS 6.0 Filter Driver-0003
Intel(R) Ethernet Connection (2) I218-V-QoS Packet Scheduler-0000
Intel(R) Ethernet Connection (2) I218-V-HHD Software NDIS 6.0 Filter Driver-0004
Intel(R) Ethernet Connection (2) I218-V-WFP 802.3 MAC Layer LightWeight Filter-0000
Intel(R) Ethernet Connection (2) I218-V-HHD Software NDIS 6.0 Filter Driver-0005
Broadcom 802.11ac Network Adapter-WFP Native MAC Layer LightWeight Filter-0000
Broadcom 802.11ac Network Adapter-Virtual WiFi Filter Driver-0000
Broadcom 802.11ac Network Adapter-Native WiFi Filter Driver-0000
Broadcom 802.11ac Network Adapter-HHD Software NDIS 6.0 Filter Driver-0003
Broadcom 802.11ac Network Adapter-Shrew Soft Lightweight Filter-0000
Broadcom 802.11ac Network Adapter-HHD Software NDIS 6.0 Filter Driver-0004
Broadcom 802.11ac Network Adapter-VirtualBox NDIS Light-Weight Filter-0000
Broadcom 802.11ac Network Adapter-HHD Software NDIS 6.0 Filter Driver-0005
Broadcom 802.11ac Network Adapter-QoS Packet Scheduler-0000
Broadcom 802.11ac Network Adapter-HHD Software NDIS 6.0 Filter Driver-0006
Broadcom 802.11ac Network Adapter-WFP 802.3 MAC Layer LightWeight Filter-0000
Broadcom 802.11ac Network Adapter-HHD Software NDIS 6.0 Filter Driver-0007
Microsoft Wi-Fi Direct Virtual Adapter-WFP Native MAC Layer LightWeight Filter-0000
Microsoft Wi-Fi Direct Virtual Adapter-Native WiFi Filter Driver-0000
Microsoft Wi-Fi Direct Virtual Adapter-HHD Software NDIS 6.0 Filter Driver-0002
Microsoft Wi-Fi Direct Virtual Adapter-Shrew Soft Lightweight Filter-0000
Microsoft Wi-Fi Direct Virtual Adapter-HHD Software NDIS 6.0 Filter Driver-0003
Microsoft Wi-Fi Direct Virtual Adapter-VirtualBox NDIS Light-Weight Filter-0000
Microsoft Wi-Fi Direct Virtual Adapter-HHD Software NDIS 6.0 Filter Driver-0004
Microsoft Wi-Fi Direct Virtual Adapter-QoS Packet Scheduler-0000
Microsoft Wi-Fi Direct Virtual Adapter-HHD Software NDIS 6.0 Filter Driver-0005
Microsoft Wi-Fi Direct Virtual Adapter-WFP 802.3 MAC Layer LightWeight Filter-0000
Microsoft Wi-Fi Direct Virtual Adapter-HHD Software NDIS 6.0 Filter Driver-0006

为了我的使用,我正在设置一个 Upnp 服务器,它有助于理解我正在寻找的“模式”。返回的一些对象是以太网适配器、网络适配器、虚拟网络适配器、驱动程序和 VPN 客户端适配器。也不是所有东西都有地址。所以你会想要跳过那些没有的接口对象。

您还可以将此添加到当前 NetworkInterface i 的循环中

while(interfaces.hasMoreElements()){
    Enumeration<InetAddress> addresses = i.getInetAddresses();
    System.out.println(i.getDisplayName());
    System.out.println("\t- name:" + i.getName());
    System.out.println("\t- idx:" + i.getIndex());
    System.out.println("\t- max trans unit (MTU):" + i.getMTU());
    System.out.println("\t- is loopback:" + i.isLoopback());
    System.out.println("\t- is PPP:" + i.isPointToPoint());
    System.out.println("\t- isUp:" + i.isUp());
    System.out.println("\t- isVirtual:" + i.isVirtual());
    System.out.println("\t- supportsMulticast:" + i.supportsMulticast());
}

您将在输出中看到如下信息:

Software Loopback Interface 1
    - name:lo
    - idx:1
    - max trans unit (MTU):-1
    - is loopback:true
    - is PPP:false
    - isUp:true
    - isVirtual:false
    - supportsMulticast:true
        -ADRESS: [127.0.0.1(VIKING-192.168.56.1)]127.0.0.1:127.0.0.1 - [B@19e1023e
        -ADRESS: [0:0:0:0:0:0:0:1(VIKING-192.168.56.1)]0:0:0:0:0:0:0:1:0:0:0:0:0:0:0:1 - [B@7cef4e59
Broadcom 802.11ac Network Adapter
    - name:wlan0
    - idx:2
    - max trans unit (MTU):1500
    - is loopback:false
    - is PPP:false
    - isUp:true
    - isVirtual:false
    - supportsMulticast:true
        -ADRESS: [VIKING.monkeybrains.net(VIKING-192.168.56.1)]VIKING.monkeybrains.net:192.168.1.142 - [B@64b8f8f4
        -ADRESS: [fe80:0:0:0:81fa:31d:21c9:85cd%wlan0(VIKING-192.168.56.1)]fe80:0:0:0:81fa:31d:21c9:85cd%wlan0:fe80:0:0:0:81fa:31d:21c9:85cd%wlan0 - [B@2db0f6b2
Microsoft Kernel Debug Network Adapter
    - name:eth0
    - idx:3
    - max trans unit (MTU):-1
    - is loopback:false
    - is PPP:false
    - isUp:false
    - isVirtual:false
    - supportsMulticast:true

v
vdeantoni

使用 InetAddress.getLocalHost() 获取本地地址

import java.net.InetAddress;

try {
  InetAddress addr = InetAddress.getLocalHost();            
  System.out.println(addr.getHostAddress());
} catch (UnknownHostException e) {
}

我的 PPP 连接 IP 地址是:117.204.44.192 但上面返回我 192.168.1.2
您需要抓取所有可用的 InetAddress 实例并找出正确的实例。
多余的答案:stackoverflow.com/a/25257429/139985 说了同样的话。
t
twatson0990
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.util.Enumeration;

public class IpAddress {

NetworkInterface ifcfg;
Enumeration<InetAddress> addresses;
String address;

public String getIpAddress(String host) {
    try {
        ifcfg = NetworkInterface.getByName(host);
        addresses = ifcfg.getInetAddresses();
        while (addresses.hasMoreElements()) {
            address = addresses.nextElement().toString();
            address = address.replace("/", "");
        }
    } catch (Exception e) {
        e.printStackTrace();
    }
    return ifcfg.toString();
}
}

P
Pantelis Natsiavas

一种相当简单的方法,似乎正在工作......

String getPublicIPv4() throws UnknownHostException, SocketException{
    Enumeration<NetworkInterface> e = NetworkInterface.getNetworkInterfaces();
    String ipToReturn = null;
    while(e.hasMoreElements())
    {
        NetworkInterface n = (NetworkInterface) e.nextElement();
        Enumeration<InetAddress> ee = n.getInetAddresses();
        while (ee.hasMoreElements())
        {
            InetAddress i = (InetAddress) ee.nextElement();
            String currentAddress = i.getHostAddress();
            logger.trace("IP address "+currentAddress+ " found");
            if(!i.isSiteLocalAddress()&&!i.isLoopbackAddress() && validate(currentAddress)){
                ipToReturn = currentAddress;    
            }else{
                System.out.println("Address not validated as public IPv4");
            }

        }
    }

    return ipToReturn;
}

private static final Pattern IPv4RegexPattern = Pattern.compile(
        "^(([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\.){3}([01]?\\d\\d?|2[0-4]\\d|25[0-5])$");

public static boolean validate(final String ip) {
    return IPv4RegexPattern.matcher(ip).matches();
}

Y
Youcef Laidani

通常,当我尝试查找我的公共 IP 地址(如 cmyip.comwww.iplocation.net)时,我使用这种方式:

public static String myPublicIp() {

    /*nslookup myip.opendns.com resolver1.opendns.com*/
    String ipAdressDns  = "";
    try {
        String command = "nslookup myip.opendns.com resolver1.opendns.com";
        Process proc = Runtime.getRuntime().exec(command);

        BufferedReader stdInput = new BufferedReader(new InputStreamReader(proc.getInputStream()));

        String s;
        while ((s = stdInput.readLine()) != null) {
            ipAdressDns  += s + "\n";
        }
    } catch (IOException e) {
        e.printStackTrace();
    }

    return ipAdressDns ;
}

1
124697

如果您的机器是网络的一部分,这将获取您的网络的 IP 地址

try {
    System.out.println(InetAddress.getLocalHost().getHostAddress());
} catch (UnknownHostException e) {
    e.printStackTrace();
}

多余的答案。其他(较早的)答案说同样的话。
S
SepJaPro2.4

由于我的系统(与许多其他系统一样)具有各种网络接口。InetAddress.getLocalHost()Inet4Address.getLocalHost() 只是返回了一个我不想要的。因此我不得不使用这种幼稚的方法。

InetAddress[] allAddresses = Inet4Address.getAllByName("YourComputerHostName");
        InetAddress desiredAddress;
        //In order to find the desired Ip to be routed by other modules (WiFi adapter)
        for (InetAddress address :
                allAddresses) {
            if (address.getHostAddress().startsWith("192.168.2")) {
                desiredAddress = address;
            }
        }
// Use the desired address for whatever purpose.

请注意,在这种方法中,我已经知道我想要的 IP 地址在 192.168.2 子网中。


P
Peter Walser

您的计算机可以有多个 NetworkInterface,每个都有多个 InetAddress。如果您过滤掉任何本地地址,则提醒的地址是非本地地址,您可以有一个,没有或多个。

不幸的是,Java 中的网络 API 仍然使用(旧的)枚举而不是迭代器和流,我们可以通过将它们包装为流来应对。所以我们需要做的就是

流过所有网络接口及其地址,以及

过滤掉本地的

代码:

private Stream<InetAddress> getNonLocalIpAddresses() throws IOException {
    return enumerationAsStream(NetworkInterface.getNetworkInterfaces())
        .flatMap(networkInterface -> enumerationAsStream(networkInterface.getInetAddresses()))
        .filter(inetAddress -> !inetAddress.isAnyLocalAddress())
        .filter(inetAddress -> !inetAddress.isSiteLocalAddress())
        .filter(inetAddress -> !inetAddress.isLoopbackAddress())
        .filter(inetAddress -> !inetAddress.isLinkLocalAddress());
}

在我的机器上,这当前返回两个 IPv6 地址。

要获得这些 InetAdresses 中的第一个:

private String getMyIp() throws IOException {
    return getNonLocalIpAddresses()
        .map(InetAddress::getHostAddress)
        .findFirst()
        .orElseThrow(NoSuchElementException::new);
}

将枚举包装为流的方法:

public static <T> Stream<T> enumerationAsStream(Enumeration<T> e) {
    return StreamSupport.stream(
        Spliterators.spliteratorUnknownSize(
            new Iterator<>() {
                public T next() { return e.nextElement();  }
                public boolean hasNext() { return e.hasMoreElements(); }
            }, Spliterator.ORDERED), false);
}