Java 获取本机的外网 IP

原理 通过 HTTP 访问第三方获取 IP 的服务接口获取本机的外网 IP,例如:

  • http://checkip.amazonaws.com/
  • https://ipv4.icanhazip.com/
  • http://bot.whatismyipaddress.com/
  • 等等...
【Java 获取本机的外网 IP】考虑到这些第三方接口不一定 100% 稳定,例如可能出现下线、错误、访问超时或太慢的情况,所以不能仅依赖其中之一。
下面提供一种方案,并发访问这些服务接口,并返回第一个成功的结果,也就是其中最快的一个返回结果。
实现
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 {/** * IP 地址校验的正则表达式 */ 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])$"); /** * 获取 IP 地址的服务列表 */ 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 callables = new ArrayList<>(); for (String ipService : IPV4_SERVICES) { callables.add(() -> get(ipService)); }ExecutorService executorService = Executors.newCachedThreadPool(); try { // 返回第一个成功获取的 IP 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); } } } }

线程池的 ExecutorService.invokeAny(callables) 方法用于并发执行多个线程,并拿到最快的执行成功的线程的返回值,只要有一个执行成功,其他失败的任务都会忽略。但是如果全部失败,例如本机根本就没有连外网,那么就会抛出 ExecutionException 异常。
关注我的公众号 Java 获取本机的外网 IP
文章图片

    推荐阅读