【问题标题】:Getting the 'external' IP address in Java在 Java 中获取“外部”IP 地址
【发布时间】:2011-02-25 17:20:20
【问题描述】:

我不太清楚如何获取机器的外部 IP 地址,因为网络外部的计算机会看到它。

我下面的 IPAddress 类只获取机器的本地 IP 地址。

public class IPAddress {

    private InetAddress thisIp;

    private String thisIpAddress;

    private void setIpAdd() {
        try {
            InetAddress thisIp = InetAddress.getLocalHost();
            thisIpAddress = thisIp.getHostAddress().toString();
        } catch (Exception e) {
        }
    }

    protected String getIpAddress() {
        setIpAdd();
        return thisIpAddress;
    }
}

【问题讨论】:

  • 您知道一台机器可以同时拥有多个公共地址吗?它们实际上与网络接口相关联,而不是与机器相关联。

标签: java networking network-programming ip-address external


【解决方案1】:

我不确定您是否可以从本地机器上运行的代码中获取该 IP。

但是,您可以构建在网站上运行的代码,比如在 JSP 中,然后使用返回请求来源 IP 的东西:

request.getRemoteAddr()

或者简单地使用已经存在的服务,然后从服务中解析答案以找出 IP。

使用 AWS 等网络服务

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

URL whatismyip = new URL("http://checkip.amazonaws.com");
BufferedReader in = new BufferedReader(new InputStreamReader(
                whatismyip.openStream()));

String ip = in.readLine(); //you get the IP as a String
System.out.println(ip);

【讨论】:

  • 警告:他们已将自动化 URL 调整为 automation.whatismyip.com/n09230945.asp
  • 我建议至少实施两台为您的 ip 提供服务的服务器,以防其中一台此时出现故障(当然要进行正确的错误处理)。我的选择是externalip.net(单击“需要 API?”链接)。已经使用该网站一年多了,到目前为止还没有遇到任何问题,而且它是一项快速的服务,总是能快速响应。
  • 很棒的链接;我将把它用作大学网络任务概念证明的一部分!
  • 另一种选择是,如果您可以访问运行 PHP 的 Web 服务器或主机帐户,只需使用上面提供的代码 @bakkal 并将其指向您自己的仅包含 echo $_SERVER['REMOTE_ADDR']; 的 PHP 文件。如果这是脚本的唯一或第一行输出,则一切就绪。
  • Whatsmyip.com 似乎不再支持这种类型的自动化。
【解决方案2】:

@stivlo 的其中一个 cmets 值得回答:

您可以使用亚马逊服务http://checkip.amazonaws.com

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.URL;

public class IpChecker {

    public static String getIp() throws Exception {
        URL whatismyip = new URL("http://checkip.amazonaws.com");
        BufferedReader in = null;
        try {
            in = new BufferedReader(new InputStreamReader(
                    whatismyip.openStream()));
            String ip = in.readLine();
            return ip;
        } finally {
            if (in != null) {
                try {
                    in.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

【讨论】:

    【解决方案3】:

    事实是:从您提出问题的意义上说,“您不能”。 NAT 发生在协议之外。您的机器内核无法知道您的 NAT 盒子是如何从外部 IP 地址映射到内部 IP 地址的。此处的其他答案提供了一些技巧,涉及与外部网站对话的方法。

    【讨论】:

    • 还是不行,因为它没有回答原始问题,而且看起来像是一个学术练习
    • 公平地说,这个答案确实回答了这个问题,而其他十几个答案基本上都说了同样的话,但显示了特定于任何给定外部 ip 检查器选择的代码或 URL。
    【解决方案4】:

    所有这些仍然正常运行! (截至 2022 年 2 月 10 日)

    忠告:不要直接依赖其中一个;尝试使用一个,但有一个考虑到其他人的应急计划!用得越多越好!

    祝你好运!

    【讨论】:

      【解决方案5】:

      正如@Donal Fellows 所写,您必须查询网络接口而不是机器。 javadocs 中的这段代码对我有用:

      以下示例程序列出了机器上的所有网络接口及其地址:

      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: TCP Loopback interface
      Name: lo
      InetAddress: /127.0.0.1
      
      Display name: Wireless Network Connection
      Name: eth0
      InetAddress: /192.0.2.0
      

      来自docs.oracle.com

      【讨论】:

      • 谢谢!虽然该解决方案在软件位于 NAT 之后时不起作用,但它对于您知道不会位于 NAT 之后的服务器软件仍然非常有帮助,或者如果软件无法连接到另一台服务器以获得它自己的服务器,它仍然非常有用知识产权。特别是对于打算在与 Internet 断开连接的 LAN 上运行的软件,这是可行的方法。
      【解决方案6】:

      创建一个到 www.whatismyip.com 之类的网站的 HttpURLConnection 并解析它:-)

      【讨论】:

        【解决方案7】:

        这个怎么样?这很简单,对我来说效果最好:)

        import java.io.BufferedReader;
        import java.io.IOException;
        import java.io.InputStreamReader;
        import java.net.MalformedURLException;
        import java.net.URL;
        
        
        public class IP {
            public static void main(String args[]) {
                new IP();
            }
        
            public IP() {
                URL ipAdress;
        
                try {
                    ipAdress = new URL("http://myexternalip.com/raw");
        
                    BufferedReader in = new BufferedReader(new InputStreamReader(ipAdress.openStream()));
        
                    String ip = in.readLine();
                    System.out.println(ip);
                } catch (MalformedURLException e) {
                    e.printStackTrace();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        

        【讨论】:

        • 这太棒了!我回家后会试试的。这正是我一直在寻找的解决问题的方法。不知道为什么它没有被投票更高。
        【解决方案8】:

        http://jstun.javawi.de/ 会做 - 只要你的网关设备做 STUN )大多数做)

        【讨论】:

        • 非常有趣,它按预期工作,无需使用外部服务,只需与网关对话。然而,GPL 许可可能会限制其采用。
        • 网站给了我一个登录屏幕。可能不是原版。
        【解决方案9】:

        这并不容易,因为局域网内的机器通常不关心其路由器到互联网的外部 IP。它根本不需要它!

        我建议您通过打开类似http://www.whatismyip.com/ 的网站并通过解析 html 结果获取 IP 号来利用此功能。这应该不难!

        【讨论】:

        • 您不必解析 html。 whatismyip.com的网页来源第一行就是你的外网IP。
        【解决方案10】:
        import java.io.BufferedReader;
        import java.io.IOException;
        import java.io.InputStreamReader;
        import java.net.URL;
        import java.util.ArrayList;
        import java.util.List;
        import java.util.concurrent.*;
        import java.util.regex.Pattern;
        
        public class ExternalIPUtil {
        
            private static final Pattern IPV4_PATTERN = Pattern.compile("^(([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\.){3}([01]?\\d\\d?|2[0-4]\\d|25[0-5])$");
        
            private static final String[] IPV4_SERVICES = {
                    "http://checkip.amazonaws.com/",
                    "https://ipv4.icanhazip.com/",
                    "http://bot.whatismyipaddress.com/"
                    // and so on ...
            };
        
            public static String get() throws ExecutionException, InterruptedException {
                List<Callable<String>> callables = new ArrayList<>();
                for (String ipService : IPV4_SERVICES) {
                    callables.add(() -> get(ipService));
                }
        
                ExecutorService executorService = Executors.newCachedThreadPool();
                try {
                    return executorService.invokeAny(callables);
                } finally {
                    executorService.shutdown();
                }
            }
        
            private static String get(String url) throws IOException {
                try (BufferedReader in = new BufferedReader(new InputStreamReader(new URL(url).openStream()))) {
                    String ip = in.readLine();
                    if (IPV4_PATTERN.matcher(ip).matches()) {
                        return ip;
                    } else {
                        throw new IOException("invalid IPv4 address: " + ip);
                    }
                }
            }
        
            public static void main(String[] args) throws ExecutionException, InterruptedException {
                System.out.println("IP: " + get());
            }
        }
        

        同时从多个 IP 服务获取,例如:

        ExecutorService.invokeAny(tasks) 返回第一个成功线程的结果。其他未完成的任务将被取消。

        【讨论】:

          【解决方案11】:

          如果您使用的是基于 JAVA 的 webapp,并且如果您想获取客户端(通过浏览器发出请求的人)的外部 ip,请尝试在 公共域 中部署该应用并使用 request.getRemoteAddr () 读取外部 IP 地址。

          【讨论】:

            【解决方案12】:
            System.out.println(pageCrawling.getHtmlFromURL("http://ipecho.net/plain"));
            

            【讨论】:

              【解决方案13】:

              另一种解决方案是执行外部命令,显然,这种解决方案限制了应用程序的可移植性。

              例如,对于在 Windows 上运行的应用程序,可以通过 jPowershell 执行 PowerShell 命令,如下代码所示:

              public String getMyPublicIp() {
                  // PowerShell command
                  String command = "(Invoke-WebRequest ifconfig.me/ip).Content.Trim()";
                  String powerShellOut = PowerShell.executeSingleCommand(command).getCommandOutput();
              
                  // Connection failed
                  if (powerShellOut.contains("InvalidOperation")) {
                      powerShellOut = null;
                  }
                  return powerShellOut;
              }
              

              【讨论】:

                猜你喜欢
                • 2014-01-25
                • 2021-11-20
                • 2013-04-03
                • 2016-03-10
                • 2013-08-04
                • 2011-03-16
                • 2017-01-26
                • 1970-01-01
                相关资源
                最近更新 更多