所以你有一个从管理 Web UI 中检索到的字符串(所以它肯定是一个字符串)。在 Java 中,如何确定该字符串是 IP 地址还是主机名?
更新:我想我没有说清楚,我更多的是问Java SDK中是否有任何东西可以用来区分IP和主机名?很抱歉造成混乱,并感谢所有花时间/将花时间回答这个问题的人。
所以你有一个从管理 Web UI 中检索到的字符串(所以它肯定是一个字符串)。在 Java 中,如何确定该字符串是 IP 地址还是主机名?
更新:我想我没有说清楚,我更多的是问Java SDK中是否有任何东西可以用来区分IP和主机名?很抱歉造成混乱,并感谢所有花时间/将花时间回答这个问题的人。
您可以使用具有此模式的正则表达式:
\b(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\b
这将告诉您它是否是 IPv4 地址。
可以查看字符串是否匹配 number.number.number.number 格式,例如:
\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\b
将匹配任何来自0 - 999
.
您可以将其默认为主机名的任何其他内容。
我们是否可以假设它是一个或另一个,而不是完全不同的东西?如果是这样,我可能会使用正则表达式来查看它是否匹配“点四边形”格式。
URI validator = new URI(yourString);
该代码将验证 IP 地址或主机名。(如果字符串无效,它会抛出格式错误的 URI 异常)
如果您想区分这两者..那么我想念您的问题。
您可以在呼叫中使用安全管理器InetAddress.getByName(addr)
。
如果 addr 不是点分四边形,getByName
将尝试执行连接以进行名称查找,安全管理器可以将其捕获为checkConnect(addr, -1)
调用,从而导致您可以捕获的抛出的 SecurityException。
如果您运行完全特权,则可以在调用System.setSecurityManager()
之前插入自定义安全管理器。getByName
它并不像看起来那么简单,连字符、下划线和方括号“-”、“_”、“[]”等字符周围存在一些歧义。
Java SDK 在这方面有一些限制。使用 InetAddress.getByName 时,它会到网络上进行 DNS 名称解析并解析地址,如果您只想检测主机与地址,这是昂贵且不必要的。此外,如果地址以稍微不同但有效的格式(在 IPv6 中很常见)写入,则对 InetAddress.getByName 的结果进行字符串比较将不起作用。
IPAddress Java 库将执行此操作。链接中提供了 javadoc。免责声明:我是项目经理。
static void check(HostName host) {
try {
host.validate();
if(host.isAddress()) {
System.out.println("address: " + host.asAddress());
} else {
System.out.println("host name: " + host);
}
} catch(HostNameException e) {
System.out.println(e.getMessage());
}
}
public static void main(String[] args) {
HostName host = new HostName("1.2.3.4");
check(host);
host = new HostName("1.2.a.4");
check(host);
host = new HostName("::1");
check(host);
host = new HostName("[::1]");
check(host);
host = new HostName("1.2.?.4");
check(host);
}
输出:
address: 1.2.3.4
host name: 1.2.a.4
address: ::1
address: ::1
1.2.?.4 Host error: invalid character at index 4
你不能只对它进行正则表达式匹配吗?
使用InetAddress#getAllByName(String hostOrIp) - 如果hostOrIp
是 IP 地址,则结果是具有单个 InetAddress 的数组,它.getHostAddress()
返回与hostOrIp
.
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.Arrays;
public class IPvsHostTest {
private static final org.slf4j.Logger LOG = org.slf4j.LoggerFactory.getLogger(IPvsHostTest.class);
@org.junit.Test
public void checkHostValidity() {
Arrays.asList("10.10.10.10", "google.com").forEach( hostname -> isHost(hostname));
}
private void isHost(String ip){
try {
InetAddress[] ips = InetAddress.getAllByName(ip);
LOG.info("IP-addresses for {}", ip);
Arrays.asList(ips).forEach( ia -> {
LOG.info(ia.getHostAddress());
});
} catch (UnknownHostException e) {
LOG.error("Invalid hostname", e);
}
}
}
输出:
IP-addresses for 10.10.10.10
10.10.10.10
IP-addresses for google.com
64.233.164.100
64.233.164.138
64.233.164.139
64.233.164.113
64.233.164.102
64.233.164.101
如果指定了主机名,此代码仍会执行 DNS 查找,但至少它会跳过可能使用其他方法执行的反向查找:
...
isDottedQuad("1.2.3.4");
isDottedQuad("google.com");
...
boolean isDottedQuad(String hostOrIP) throws UnknownHostException {
InetAddress inet = InetAddress.getByName(hostOrIP);
boolean b = inet.toString().startsWith("/");
System.out.println("Is " + hostOrIP + " dotted quad? " + b + " (" + inet.toString() + ")");
return b;
}
它生成以下输出:
Is 1.2.3.4 dotted quad? true (/1.2.3.4)
Is google.com dotted quad? false (google.com/172.217.12.238)
你认为我们可以期待 toString() 行为很快改变吗?