优化公网ip解析。
This commit is contained in:
@@ -376,7 +376,7 @@ public class AgentUtil {
|
||||
// 检查IP4信息
|
||||
if ("N/A".equals(gateway)) continue;
|
||||
|
||||
// 添加临时路由 过滤没有ipv4的接口
|
||||
// 添加临时路由
|
||||
// boolean flag = addTempRoute(ipv4, name, gateway);
|
||||
// if (!flag) continue;
|
||||
|
||||
@@ -501,7 +501,7 @@ public class AgentUtil {
|
||||
/**
|
||||
* 添加临时路由
|
||||
*/
|
||||
private static boolean addTempRoute(String ipv4, String name, String gateway) {
|
||||
public static boolean addTempRoute(String ipv4, String name, String gateway) {
|
||||
String prefix = "32";
|
||||
AssertLog.info("添加临时路由,ipv4:{}",ipv4);
|
||||
boolean flag = NetworkUtil.addRoute(ipv4,prefix,gateway,name);
|
||||
@@ -516,7 +516,7 @@ public class AgentUtil {
|
||||
/**
|
||||
* 删除临时路由
|
||||
*/
|
||||
private static boolean delTempRoute(String ipv4, String name, String gateway) {
|
||||
public static boolean delTempRoute(String ipv4, String name, String gateway) {
|
||||
String prefix = "32";
|
||||
AssertLog.info("删除临时路由,ipv4:{}",ipv4);
|
||||
boolean flag = NetworkUtil.deleteRoute(ipv4,prefix,gateway,name);
|
||||
@@ -644,19 +644,34 @@ public class AgentUtil {
|
||||
return null;
|
||||
}
|
||||
|
||||
// 提取网关IP地址
|
||||
// 示例行: "1 8.8.8.8 3.737 ms 3.940 ms 4.128 ms"
|
||||
Pattern pattern = Pattern.compile("\\d+\\.\\d+\\.\\d+\\.\\d+");
|
||||
Matcher matcher = pattern.matcher(line);
|
||||
// 情况1:匹配 "1 192.168.9.1 (192.168.9.1)" 这种格式(图片中的格式)
|
||||
// 先尝试匹配括号中的IP(最可靠)
|
||||
Pattern bracketPattern = Pattern.compile("\\(([\\d.]+)\\)");
|
||||
Matcher bracketMatcher = bracketPattern.matcher(line);
|
||||
|
||||
if (matcher.find()) {
|
||||
String gatewayIp = matcher.group(0);
|
||||
if (bracketMatcher.find()) {
|
||||
String gatewayIp = bracketMatcher.group(1);
|
||||
AssertLog.info("traceroute 探测完成,网卡名称:{},网关IP:{}", interfaceName, gatewayIp);
|
||||
return gatewayIp;
|
||||
}
|
||||
|
||||
// 如果没有匹配到IP格式,尝试查找主机名
|
||||
// 行格式可能是: "1 gateway.local (192.168.1.1) 0.5 ms"
|
||||
// 情况2:匹配 "1 8.8.8.8 3.737 ms" 这种纯IP格式(没有括号)
|
||||
// 使用更精确的正则,只匹配数字开头且包含点号的IP地址
|
||||
// 确保不匹配到主机名中的点号(如201.108.141.116.adsl-pool.jlccptt.net.cn)
|
||||
Pattern ipPattern = Pattern.compile("^\\s*1\\s+(\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3})(?:\\s|$)");
|
||||
Matcher ipMatcher = ipPattern.matcher(line);
|
||||
|
||||
if (ipMatcher.find()) {
|
||||
String gatewayIp = ipMatcher.group(1);
|
||||
// 验证是否是合法IP(避免匹配到主机名中的数字序列)
|
||||
if (isValidIP(gatewayIp)) {
|
||||
AssertLog.info("traceroute 探测完成,网卡名称:{},网关IP:{}", interfaceName, gatewayIp);
|
||||
return gatewayIp;
|
||||
}
|
||||
}
|
||||
|
||||
// 情况3:匹配 "1 gateway.local 0.5 ms" 或 "1 201.108.141.116.adsl-pool.jlccptt.net.cn" 这种主机名格式
|
||||
// 提取第一跳后的第二个字段(跳过序号)
|
||||
String[] parts = line.trim().split("\\s+");
|
||||
if (parts.length >= 2 && !parts[1].equals("*")) {
|
||||
String gateway = parts[1];
|
||||
@@ -675,6 +690,30 @@ public class AgentUtil {
|
||||
}
|
||||
}
|
||||
|
||||
// 辅助方法:验证IP地址是否合法
|
||||
private static boolean isValidIP(String ip) {
|
||||
if (ip == null || ip.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
String[] parts = ip.split("\\.");
|
||||
if (parts.length != 4) {
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
for (String part : parts) {
|
||||
int num = Integer.parseInt(part);
|
||||
if (num < 0 || num > 255) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
} catch (NumberFormatException e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// 检查接口是否“已连接”(物理链路状态)
|
||||
private static boolean isInterfaceConnected(String interfaceName) {
|
||||
try {
|
||||
|
||||
@@ -74,21 +74,42 @@ public class NetworkInterfaceUtil {
|
||||
AssertLog.info(" 跳过网卡 {}: 无法获取网关", name);
|
||||
continue;
|
||||
}
|
||||
|
||||
boolean flag = false;
|
||||
if(!"N/A".equals(ipv4) && gateway != null){
|
||||
flag = true;
|
||||
}
|
||||
// 获取公网IP
|
||||
String publicIp = null;
|
||||
String ipInfo = null;
|
||||
if (gateway != null) {
|
||||
ipInfo = PublicIpFetcher.getPublicIp();
|
||||
publicIp = PublicIpFetcher.extractIp(ipInfo);
|
||||
if (publicIp != null) {
|
||||
AssertLog.info(" 公网 IP: {}", publicIp);
|
||||
} else {
|
||||
AssertLog.info(" 未能提取公网 IP 地址");
|
||||
}
|
||||
if (StringUtils.isBlank(publicIp)) {
|
||||
AssertLog.info(" 跳过网卡 {}: 无公网IP", name);
|
||||
continue;
|
||||
if (flag) {
|
||||
List<String> publicIps = PublicIpFetcher.getPublicIps();
|
||||
|
||||
if (publicIps != null && !publicIps.isEmpty()) {
|
||||
AssertLog.info("网卡 {} nslookup获取到 {} 个公网IP: {}", name, publicIps.size(), publicIps);
|
||||
|
||||
for (String ip : publicIps) {
|
||||
if (ip != null && !ip.isEmpty()) {
|
||||
// 为每个公网IP添加临时路由
|
||||
boolean routeAdded = AgentUtil.addTempRoute(ip, name, gateway);
|
||||
}
|
||||
}
|
||||
ipInfo = PublicIpFetcher.getPublicIp();
|
||||
publicIp = PublicIpFetcher.extractIp(ipInfo);
|
||||
if (publicIp != null) {
|
||||
AssertLog.info(" 公网 IP: {}", publicIp);
|
||||
} else {
|
||||
AssertLog.info(" 未能提取公网 IP 地址");
|
||||
}
|
||||
if (StringUtils.isBlank(publicIp)) {
|
||||
AssertLog.info(" 跳过网卡 {}: 无公网IP", name);
|
||||
continue;
|
||||
}
|
||||
for (String ip : publicIps) {
|
||||
if (ip != null && !ip.isEmpty()) {
|
||||
// 删除临时路由
|
||||
boolean routeAdded = AgentUtil.delTempRoute(ip, name, gateway);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -7,6 +7,7 @@ import java.net.HttpURLConnection;
|
||||
import java.net.InetAddress;
|
||||
import java.net.URL;
|
||||
import java.net.UnknownHostException;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.*;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
@@ -14,11 +15,9 @@ import java.util.regex.Pattern;
|
||||
public class PublicIpFetcher {
|
||||
|
||||
// 主备IP查询服务
|
||||
private static final String PRIMARY_IP_SERVICE = "https://myip.ipip.net";
|
||||
private static final String FALLBACK_IP_SERVICE = "http://cip.cc";
|
||||
|
||||
private static final int TIMEOUT_MS = 8_000; // 8秒超时
|
||||
private static final int CURL_TIMEOUT_MS = 5_000; // curl命令执行超时
|
||||
private static final String PRIMARY_IP_SERVICE = "myip.ipip.net";
|
||||
private static final String FALLBACK_IP_SERVICE = "cip.cc";
|
||||
private static final int TIMEOUT_MS = 5_000; // 5秒超时
|
||||
|
||||
// 正则表达式匹配
|
||||
private static final String IPV4_PATTERN = "(\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3})";
|
||||
@@ -31,50 +30,202 @@ public class PublicIpFetcher {
|
||||
);
|
||||
|
||||
/**
|
||||
* 获取公网 IP 信息(带降级策略)
|
||||
* 1. 首先尝试 myip.ipip.net
|
||||
* 2. 如果超时或失败,执行 curl cip.cc
|
||||
* 3. 如果都失败,返回本地IP
|
||||
* 获取公网 IP 列表(带降级策略)
|
||||
* 1. 首先尝试 nslookup myip.ipip.net
|
||||
* 2. 如果失败,尝试 nslookup cip.cc
|
||||
*/
|
||||
public static String getPublicIp() {
|
||||
// 方法1: 尝试主服务
|
||||
String ipInfo = tryPrimaryService();
|
||||
if (ipInfo != null && !ipInfo.isEmpty()) {
|
||||
return ipInfo;
|
||||
public static List<String> getPublicIps() {
|
||||
List<String> ipList = new ArrayList<>();
|
||||
|
||||
// 方法1: 尝试nslookup主服务
|
||||
ipList = parseNslookupResult(PRIMARY_IP_SERVICE);
|
||||
if (!ipList.isEmpty()) {
|
||||
AssertLog.info("nslookup {} 解析到IP: {}", PRIMARY_IP_SERVICE, ipList);
|
||||
return ipList;
|
||||
}
|
||||
|
||||
// 方法2: 尝试备用服务
|
||||
ipInfo = tryFallbackService();
|
||||
if (ipInfo != null && !ipInfo.isEmpty()) {
|
||||
return ipInfo;
|
||||
// 方法2: 尝试nslookup备用服务
|
||||
ipList = parseNslookupResult(FALLBACK_IP_SERVICE);
|
||||
if (!ipList.isEmpty()) {
|
||||
AssertLog.info("nslookup {} 解析到IP: {}", FALLBACK_IP_SERVICE, ipList);
|
||||
return ipList;
|
||||
}
|
||||
|
||||
// 方法3: 返回本地IP
|
||||
return getLocalIpInfo();
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
/**
|
||||
* 尝试主服务 (myip.ipip.net)
|
||||
* 执行nslookup并解析结果
|
||||
*/
|
||||
private static String tryPrimaryService() {
|
||||
private static List<String> parseNslookupResult(String domain) {
|
||||
List<String> ipList = new ArrayList<>();
|
||||
|
||||
try {
|
||||
// 执行nslookup命令
|
||||
Process process = new ProcessBuilder("nslookup", domain)
|
||||
.redirectErrorStream(true)
|
||||
.start();
|
||||
|
||||
// 等待命令执行完成
|
||||
boolean finished = process.waitFor(TIMEOUT_MS, TimeUnit.MILLISECONDS);
|
||||
|
||||
if (!finished) {
|
||||
process.destroyForcibly();
|
||||
return ipList;
|
||||
}
|
||||
|
||||
int exitCode = process.exitValue();
|
||||
if (exitCode != 0) {
|
||||
return ipList;
|
||||
}
|
||||
|
||||
// 读取并解析输出
|
||||
try (BufferedReader reader = new BufferedReader(
|
||||
new InputStreamReader(process.getInputStream()))) {
|
||||
|
||||
StringBuilder output = new StringBuilder();
|
||||
String line;
|
||||
|
||||
while ((line = reader.readLine()) != null) {
|
||||
output.append(line).append("\n");
|
||||
|
||||
// 1. 查找"Address:"行
|
||||
if (line.contains("Address:") && !line.contains("#")) {
|
||||
Matcher matcher = IP_PATTERN.matcher(line);
|
||||
while (matcher.find()) {
|
||||
String ip = matcher.group(1);
|
||||
// 过滤DNS服务器IP和本地回环地址
|
||||
if (!isDnsServerIp(ip) && !isLocalIp(ip)) {
|
||||
ipList.add(ip);
|
||||
}
|
||||
}
|
||||
}
|
||||
// 2. 查找"Name:"行后的IP地址
|
||||
else if (line.trim().startsWith("Name:")) {
|
||||
// 读取下一行,通常是Address行
|
||||
String nextLine = reader.readLine();
|
||||
if (nextLine != null) {
|
||||
output.append(nextLine).append("\n");
|
||||
Matcher matcher = IP_PATTERN.matcher(nextLine);
|
||||
while (matcher.find()) {
|
||||
String ip = matcher.group(1);
|
||||
if (!isDnsServerIp(ip) && !isLocalIp(ip)) {
|
||||
ipList.add(ip);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 3. 如果以上方法都没找到,尝试在整个输出中匹配
|
||||
if (ipList.isEmpty()) {
|
||||
String allOutput = output.toString();
|
||||
Matcher matcher = IP_PATTERN.matcher(allOutput);
|
||||
while (matcher.find()) {
|
||||
String ip = matcher.group(1);
|
||||
// 跳过DNS服务器IP和本地地址
|
||||
if (!isDnsServerIp(ip) && !isLocalIp(ip)) {
|
||||
// 检查是否是DNS服务器IP(通常在输出开头)
|
||||
boolean isDnsLine = false;
|
||||
String[] lines = allOutput.split("\n");
|
||||
for (int i = 0; i < Math.min(3, lines.length); i++) {
|
||||
if (lines[i].contains("Server:") && lines[i].contains(ip)) {
|
||||
isDnsLine = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!isDnsLine) {
|
||||
ipList.add(ip);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} catch (IOException e) {
|
||||
AssertLog.error("执行nslookup命令失败: {}", e.getMessage());
|
||||
} catch (InterruptedException e) {
|
||||
Thread.currentThread().interrupt();
|
||||
AssertLog.error("nslookup命令被中断");
|
||||
} catch (Exception e) {
|
||||
AssertLog.error("nslookup解析异常: {}", e.getMessage());
|
||||
}
|
||||
|
||||
// 去重
|
||||
return new ArrayList<>(new LinkedHashSet<>(ipList));
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查是否为DNS服务器IP
|
||||
*/
|
||||
private static boolean isDnsServerIp(String ip) {
|
||||
// 常见的DNS服务器IP段
|
||||
return ip.startsWith("8.8.") || // Google DNS
|
||||
ip.startsWith("114.114.") || // 114DNS
|
||||
ip.startsWith("119.29.") || // 腾讯DNS
|
||||
ip.startsWith("223.5.5.") || // 阿里DNS
|
||||
ip.startsWith("180.76.76.76") || // 百度DNS
|
||||
ip.startsWith("1.2.4.8") || // CNNIC DNS
|
||||
ip.startsWith("208.67."); // OpenDNS
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查是否为本地IP
|
||||
*/
|
||||
private static boolean isLocalIp(String ip) {
|
||||
return ip.startsWith("127.") ||
|
||||
ip.startsWith("192.168.") ||
|
||||
ip.startsWith("10.") ||
|
||||
ip.startsWith("172.16.") ||
|
||||
ip.startsWith("172.17.") ||
|
||||
ip.startsWith("172.18.") ||
|
||||
ip.startsWith("172.19.") ||
|
||||
ip.startsWith("172.20.") ||
|
||||
ip.startsWith("172.21.") ||
|
||||
ip.startsWith("172.22.") ||
|
||||
ip.startsWith("172.23.") ||
|
||||
ip.startsWith("172.24.") ||
|
||||
ip.startsWith("172.25.") ||
|
||||
ip.startsWith("172.26.") ||
|
||||
ip.startsWith("172.27.") ||
|
||||
ip.startsWith("172.28.") ||
|
||||
ip.startsWith("172.29.") ||
|
||||
ip.startsWith("172.30.") ||
|
||||
ip.startsWith("172.31.") ||
|
||||
ip.equals("0.0.0.0") ||
|
||||
ip.equals("255.255.255.255");
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取公网 IP 信息(保持原有逻辑,用于降级)
|
||||
*/
|
||||
public static String getPublicIp() {
|
||||
return getPublicIpInfo();
|
||||
}
|
||||
|
||||
/**
|
||||
* 原有HTTP查询逻辑
|
||||
*/
|
||||
private static String getPublicIpInfo() {
|
||||
ExecutorService executor = Executors.newSingleThreadExecutor();
|
||||
Future<String> future = executor.submit(() -> {
|
||||
try {
|
||||
AssertLog.info("myip.ipip.net采集IP信息成功");
|
||||
return fetchFromUrl(PRIMARY_IP_SERVICE, "UTF-8");
|
||||
String result = fetchFromUrl("https://" + PRIMARY_IP_SERVICE, "UTF-8");
|
||||
AssertLog.info("HTTP {}采集IP信息成功", PRIMARY_IP_SERVICE);
|
||||
return result;
|
||||
} catch (Exception e) {
|
||||
AssertLog.error("主服务请求失败: {}", e.getMessage());
|
||||
return null;
|
||||
AssertLog.error("HTTP主服务请求失败: {}", e.getMessage());
|
||||
return tryHttpFallback();
|
||||
}
|
||||
});
|
||||
|
||||
try {
|
||||
return future.get(TIMEOUT_MS, TimeUnit.MILLISECONDS);
|
||||
} catch (TimeoutException e) {
|
||||
AssertLog.error("主服务请求超时");
|
||||
AssertLog.error("HTTP请求超时");
|
||||
future.cancel(true);
|
||||
} catch (Exception e) {
|
||||
AssertLog.error("主服务执行异常: {}", e.getMessage());
|
||||
AssertLog.error("HTTP请求异常: {}", e.getMessage());
|
||||
} finally {
|
||||
executor.shutdownNow();
|
||||
}
|
||||
@@ -82,17 +233,16 @@ public class PublicIpFetcher {
|
||||
}
|
||||
|
||||
/**
|
||||
* 尝试备用服务 (curl cip.cc)
|
||||
* HTTP回退查询
|
||||
*/
|
||||
private static String tryFallbackService() {
|
||||
private static String tryHttpFallback() {
|
||||
try {
|
||||
Process process = new ProcessBuilder("curl", "-s", "--max-time", "5", FALLBACK_IP_SERVICE)
|
||||
Process process = new ProcessBuilder("curl", "-s", "--max-time", "5",
|
||||
"http://" + FALLBACK_IP_SERVICE)
|
||||
.redirectErrorStream(true)
|
||||
.start();
|
||||
|
||||
// 等待进程完成
|
||||
boolean finished = process.waitFor(CURL_TIMEOUT_MS, TimeUnit.MILLISECONDS);
|
||||
|
||||
boolean finished = process.waitFor(5_000, TimeUnit.MILLISECONDS);
|
||||
if (finished && process.exitValue() == 0) {
|
||||
try (BufferedReader reader = new BufferedReader(
|
||||
new InputStreamReader(process.getInputStream()))) {
|
||||
@@ -101,22 +251,12 @@ public class PublicIpFetcher {
|
||||
while ((line = reader.readLine()) != null) {
|
||||
result.append(line).append("\n");
|
||||
}
|
||||
AssertLog.info("curl cip.cc采集IP信息成功");
|
||||
AssertLog.info("curl {} 采集IP信息成功", FALLBACK_IP_SERVICE);
|
||||
return parseCipCcResult(result.toString());
|
||||
}
|
||||
} else {
|
||||
if (!finished) {
|
||||
process.destroyForcibly();
|
||||
}
|
||||
AssertLog.error("curl命令执行失败");
|
||||
}
|
||||
} catch (IOException e) {
|
||||
AssertLog.error("执行curl命令IO异常: {}", e.getMessage());
|
||||
} catch (InterruptedException e) {
|
||||
Thread.currentThread().interrupt();
|
||||
AssertLog.error("curl命令被中断");
|
||||
} catch (Exception e) {
|
||||
AssertLog.error("备用服务异常: {}", e.getMessage());
|
||||
AssertLog.error("HTTP回退失败: {}", e.getMessage());
|
||||
}
|
||||
return null;
|
||||
}
|
||||
@@ -127,7 +267,6 @@ public class PublicIpFetcher {
|
||||
private static String fetchFromUrl(String urlString, String charset) throws IOException {
|
||||
URL url = new URL(urlString);
|
||||
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
|
||||
|
||||
connection.setRequestMethod("GET");
|
||||
connection.setConnectTimeout(TIMEOUT_MS);
|
||||
connection.setReadTimeout(TIMEOUT_MS);
|
||||
@@ -164,17 +303,16 @@ public class PublicIpFetcher {
|
||||
String city = matcher.group(4);
|
||||
String carrier = matcher.group(5);
|
||||
|
||||
// 构建类似ipip.net的格式
|
||||
return String.format("当前 IP:%s 来自于:%s %s %s %s",
|
||||
ip, country, province, city, carrier);
|
||||
}
|
||||
return result; // 返回原始结果
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取本地IP信息
|
||||
* 获取本地IP
|
||||
*/
|
||||
private static String getLocalIpInfo() {
|
||||
private static String getLocalIp() {
|
||||
try {
|
||||
String localIp = InetAddress.getLocalHost().getHostAddress();
|
||||
AssertLog.info("当前 IP:{} 来自于:本地网络", localIp);
|
||||
@@ -185,12 +323,16 @@ public class PublicIpFetcher {
|
||||
}
|
||||
}
|
||||
|
||||
private static String getLocalIpInfo() {
|
||||
String ip = getLocalIp();
|
||||
return ip != null ? String.format("当前 IP:%s 来自于:本地网络", ip) : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 从IP信息中提取IP地址
|
||||
*/
|
||||
public static String extractIp(String ipInfo) {
|
||||
if (ipInfo == null || ipInfo.isEmpty()) return null;
|
||||
|
||||
Matcher matcher = IP_PATTERN.matcher(ipInfo);
|
||||
return matcher.find() ? matcher.group(1) : null;
|
||||
}
|
||||
@@ -266,25 +408,22 @@ public class PublicIpFetcher {
|
||||
}
|
||||
|
||||
/**
|
||||
* 使用示例
|
||||
* 测试方法
|
||||
*/
|
||||
public static void main(String[] args) {
|
||||
System.out.println("开始获取公网IP信息...");
|
||||
System.out.println("开始获取公网IP列表...");
|
||||
|
||||
String ipInfo = getPublicIp();
|
||||
System.out.println("完整信息: " + ipInfo);
|
||||
// 测试nslookup解析
|
||||
System.out.println("测试解析myip.ipip.net:");
|
||||
List<String> ipList1 = parseNslookupResult(PRIMARY_IP_SERVICE);
|
||||
System.out.println("解析结果: " + ipList1);
|
||||
|
||||
String pureIp = extractIp(ipInfo);
|
||||
System.out.println("公网 IP: " + (pureIp != null ? pureIp : "获取失败"));
|
||||
System.out.println("\n测试解析cip.cc:");
|
||||
List<String> ipList2 = parseNslookupResult(FALLBACK_IP_SERVICE);
|
||||
System.out.println("解析结果: " + ipList2);
|
||||
|
||||
IpLocationInfo location = extractLocation(ipInfo);
|
||||
System.out.println(location);
|
||||
|
||||
// 提取需要的字段
|
||||
if (location.ip != null) {
|
||||
System.out.println("省份: " + location.getProvince());
|
||||
System.out.println("城市: " + location.getCity());
|
||||
System.out.println("运营商: " + location.getCarrier());
|
||||
}
|
||||
// 获取公网IP列表
|
||||
List<String> allIps = getPublicIps();
|
||||
System.out.println("\n最终获取到的公网IP列表: " + allIps);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user