Java:验证并将“host:port”转换为InetSocketAddress的常用方法?

2022-09-01 07:17:40

在 Java 中,验证表单的字符串并将其转换为 ?host:portInetSocketAddress

如果满足以下标准,那就太好了:

  • 无地址查找;

  • 适用于 IPv4、IPv6 和“字符串”主机名;
    (对于IPv4,它是ip:port,对于IPv6,它是[ip]:p ort,对吧?有没有一些RFC定义了所有这些方案?

  • 最好不要手动解析字符串。
    (我正在考虑所有这些特殊情况,当有人认为他知道所有有效形式的套接字地址,但忘记了导致意外结果的“特殊情况”。


答案 1

我自己提出了一个可能的解决方法。

将字符串转换为 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 ()、IPv6 () 和主机名 ()。1.1.1.1:123[::0]:123my.host.com:123

意外地,此解决方案非常适合我的方案。无论如何,我打算使用URI方案。


答案 2

正则表达式将非常巧妙地执行此操作:

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));
}

您可以通过多种方式执行此操作,例如使端口可选或在主机上执行某些验证。


推荐