【问题标题】:Getting the IP address of the current machine using Java使用Java获取当前机器的IP地址
【发布时间】:2012-03-17 22:05:19
【问题描述】:

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

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

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

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

  1. 如果可用,我需要客户端注册其 PPP IP;
  2. 否则 LAN IP(如果可用);
  3. 否则它必须注册 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());
    }
}

我能够获取所有NetworkInterfaces 关联的所有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。所以应该不是问题,我猜。

标签: java sockets ip


【解决方案1】:

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

InetAddress.getLocalHost().getHostAddress();

【讨论】:

【解决方案2】:

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

使用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 说同样的话。
【解决方案4】:

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

从表面上看,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时发生的事情
【解决方案5】:

编辑 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);
    }
}

实际版本:这停止工作

希望这个 sn-p 可以帮助您实现这一目标:

// 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 地址。
【解决方案6】:

在此处发布来自https://issues.apache.org/jira/browse/JCS-40 的测试 IP 模糊解决方法代码(Linux 系统上的 InetAddress.getLocalHost() 模糊):

/**
 * 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 ..?, 是不是一直都应该这样修剪..?
【解决方案7】:

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
  }

【讨论】:

    【解决方案8】:
    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();
    }
    }
    

    【讨论】:

      【解决方案9】:

      首先导入类

      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地址!
      【解决方案10】:
      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;
          }
      

      【讨论】:

      • 请考虑添加一些关于您的代码功能的说明。
      【解决方案11】:

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

      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();
      }
      

      【讨论】:

        【解决方案12】:

        这是上面接受的答案的一个工作示例! 此 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
        

        【讨论】:

          【解决方案13】:
          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
          【解决方案14】:

          通常当我尝试查找我的公共 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 ;
          }
          

          【讨论】:

            【解决方案15】:

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

            当您连接到不同的端点时,将自动选择使用不同的“本地”地址。例如,当您连接到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() :)
            【解决方案16】:

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

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

            【讨论】:

            • 冗余答案。其他(较早的)答案说同样的话。
            【解决方案17】:

            因为我的系统(像许多其他系统一样)有各种网络接口。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 子网中。

            【讨论】:

              【解决方案18】:

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

              不幸的是,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);
              }
              

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 2016-12-04
                • 1970-01-01
                • 1970-01-01
                • 2017-02-10
                • 2013-04-29
                • 1970-01-01
                相关资源
                最近更新 更多