Java: Распространенный способ проверить и преобразовать “host:port” в InetSocketAddress?

Каков распространенный способ в Java, чтобы проверить и преобразовать строку формы host:port в экземпляр InetSocketAddress?

Было бы хорошо, если бы следующим критериям соответствовали:

  • Никакие поиски адреса;

  • Работая на IPv4, IPv6 и "строковые" имена узлов;
    (Для IPv4 это ip:port, для IPv6 это [ip]:port, право? Есть ли некоторый RFC, который определяет все эти схемы?)

  • Предпочтительный, не анализируя строку вручную.
    (Я думаю обо всех тех особых случаях, когда кто-то думает, что знает все допустимые формы адресов сокета, но забывает о, "что особый случай", который приводит к неожиданным результатам.)

28
задан java.is.for.desktop 26 February 2010 в 21:48
поделиться

4 ответа

Я сам предлагаю одно возможное решение.

Преобразуйте строку в 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.

48
ответ дан 28 November 2019 в 02:43
поделиться

Регулярное выражение будет делать это довольно аккуратно:

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

Вы можете сделать это разными способами, например сделать порт необязательным или выполнить некоторую проверку на хосте.

8
ответ дан 28 November 2019 в 02:43
поделиться
new InetSocketAddress(
  addressString.substring(0, addressString.lastIndexOf(":")),
  Integer.parseInt(addressString.substring(addressString.lastIndexOf(":")+1, addressString.length));

? Я, наверное, совершил небольшую глупую ошибку. и я предполагаю, что вам просто нужен новый объект InetSocketAddress из String только в этом формате. хост: порт

2
ответ дан 28 November 2019 в 02:43
поделиться

Другой человек дал ответ по regex, что я и собирался сделать, когда первоначально задавал вопрос о хостах. Я все равно сделаю это, потому что это пример regex, который немного более продвинут и может помочь определить, с каким адресом вы имеете дело.

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+))?" и затем проверьте на null для group(2) и т.д.

Edit: Отмечу, что не существует "общего способа", о котором я знаю, но вышеописанное - это то, как я бы сделал это, если бы мне пришлось.

Также обратите внимание: случай IPv4 можно убрать, если случаи хоста и IPv4 будут обрабатываться одинаково. Я разделил их, потому что иногда можно избежать поиска конечного хоста, если вы знаете, что у вас есть IP-адрес.

6
ответ дан 28 November 2019 в 02:43
поделиться
Другие вопросы по тегам:

Похожие вопросы: