栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

Java 获取本机的外网 IP

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Java 获取本机的外网 IP

原理

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

  • http://checkip.amazonaws.com/
  • https://ipv4.icanhazip.com/
  • http://bot.whatismyipaddress.com/
  • 等等…

考虑到这些第三方接口不一定 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 {

    
    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> 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 异常。

Gist

https://gist.github.com/wucao/811e0bbe08f2dfab527a065d052d12a5

关注我

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/270353.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号