什么是在Java中常见的方式来验证和形式host:port
的字符串转换成InetSocketAddress
的实例?
如果以下条件得到满足这将是不错:
ip:port
,对IPv6是[ip]:port
,对不对?有没有一些RFC定义所有这些计划?)我自己提出了一个可能的解决方法解决方案。
将一个字符串转换URI(这会自动验证它),然后查询URI的主机和端口组成部分。
可悲的是,与主机组件的URI必须有一个计划。这就是为什么这个解决方案是“不完美”。
String string = ... // some string which has to be validated
try {
// WORKAROUND: add any scheme to make the resulting URI valid.
URI uri = new URI("my://" + string); // may throw URISyntaxException
String host = uri.getHost();
int port = uri.getPort();
if (uri.getHost() == null || uri.getPort() == -1) {
throw new URISyntaxException(uri.toString(),
"URI must have host and port parts");
}
// here, additional checks can be performed, such as
// presence of path, query, fragment, ...
// validation succeeded
return new InetSocketAddress (host, port);
} catch (URISyntaxException ex) {
// validation failed
}
该解决方案无需自定义字符串解析,在IPv4(1.1.1.1:123
),IPv6的([::0]:123
)和主机名(my.host.com:123
)的作品。
一不留神,这种解决方案非常适合我的方案。我还是要用URI方案。
regex将做到这一点很整齐:
Pattern p = Pattern.compile("^\\s*(.*?):(\\d+)\\s*$");
Matcher m = p.matcher("127.0.0.1:8080");
if (m.matches()) {
String host = m.group(1);
int port = Integer.parseInt(m.group(2));
}
你可以在这等多种方式使端口可选或做主机上的一些验证。
它不回答这个问题完全是,但是这个答案可能仍然是有用的人喜欢我,谁只是想解析主机和端口,但不一定是一个完整的InetAddress
。番石榴有一个HostAndPort方法parseString
类。
另一个人给了一个正则表达式的答案是我在做什么,当最初询问主机的问题做。我仍然会做,因为它是一个正则表达式是稍微更先进,可以帮助确定你正在处理什么样的地址的一个例子。
String ipPattern = "(\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}):(\\d+)";
String ipV6Pattern = "\\[([a-zA-Z0-9:]+)\\]:(\\d+)";
String hostPattern = "([\\w\\.\\-]+):(\\d+)"; // note will allow _ in host name
Pattern p = Pattern.compile( ipPattern + "|" + ipV6Pattern + "|" + hostPattern );
Matcher m = p.matcher( someString );
if( m.matches() ) {
if( m.group(1) != null ) {
// group(1) IP address, group(2) is port
} else if( m.group(3) != null ) {
// group(3) is IPv6 address, group(4) is port
} else if( m.group(5) != null ) {
// group(5) is hostname, group(6) is port
} else {
// Not a valid address
}
}
修饰使得端口可选是非常直接的。包裹 “:(\ d +)” 作为 “(?::(\ d +))?”然后检查空为基团(2)等
编辑:我注意到,有没有“共同方式”的方式,我所知道的,但上面的是我怎么会做,如果我不得不。
另外请注意:如果主机和IPv4的情况下实际上将被处理的同一IPv4的情况下,可以删除。我分裂出来,因为有时你能避免最终的主机查找,如果你知道你的IP地址。
new InetSocketAddress(
addressString.substring(0, addressString.lastIndexOf(":")),
Integer.parseInt(addressString.substring(addressString.lastIndexOf(":")+1, addressString.length));
?我大概做了一些小愚蠢的错误。和我假设你只是想要一个新的InetSocketAddress对象了String的只是格式。主持人:端口
所有类型的特殊两轮牛车,和其他地方提供优雅,但不安全的解决方案。有时不雅蛮力解决方案是这样的。
public static InetSocketAddress parseInetSocketAddress(String addressAndPort) throws IllegalArgumentException {
int portPosition = addressAndPort.length();
int portNumber = 0;
while (portPosition > 1 && Character.isDigit(addressAndPort.charAt(portPosition-1)))
{
--portPosition;
}
String address;
if (portPosition > 1 && addressAndPort.charAt(portPosition-1) == ':')
{
try {
portNumber = Integer.parseInt(addressAndPort.substring(portPosition));
} catch (NumberFormatException ignored)
{
throw new IllegalArgumentException("Invalid port number.");
}
address = addressAndPort.substring(0,portPosition-1);
} else {
portNumber = 0;
address = addressAndPort;
}
return new InetSocketAddress(address,portNumber);
}
该open-source IPAddress Java library有HostName类会做必要的分析。免责声明:我的ip地址库的项目经理。
它将分析的IPv4,IPv6和字符串主机名带或不带端口。它会处理的主机和地址的所有的各种格式。顺便说一句,对于这个没有单一的RFC,也有许多不同的方式适用RFC的。
String hostName = "[a:b:c:d:e:f:a:b]:8080";
String hostName2 = "1.2.3.4:8080";
String hostName3 = "a.com:8080";
try {
HostName host = new HostName(hostName);
host.validate();
InetSocketAddress address = host.asInetSocketAddress();
HostName host2 = new HostName(hostName2);
host2.validate();
InetSocketAddress address2 = host2.asInetSocketAddress();
HostName host3 = new HostName(hostName3);
host3.validate();
InetSocketAddress address3 = host3.asInetSocketAddress();
// use socket address
} catch (HostNameException e) {
String msg = e.getMessage();
// handle improperly formatted host name or address string
}