Намиране на безплатен порт в Java

1. Общ преглед

При стартиране на сокет сървър в нашето приложение Java, API на java.net изисква от нас да посочим безплатен номер на порт за слушане. Номерът на порта е необходим, за да може TCP слоят да идентифицира приложението, за което са предназначени входящите данни.

Посочването на номер на порт изрично не винаги е добър вариант, тъй като приложенията може вече да го заемат. Това ще доведе до изключение за вход / изход в нашето Java приложение.

В този бърз урок ще разгледаме как да проверим конкретно състояние на порта и как да използваме автоматично разпределен такъв. Ще разгледаме как това може да се направи с обикновена Java и Spring рамка. Ще разгледаме и някои други сървърни реализации, като вградени Tomcat и Jetty.

2. Проверка на състоянието на порта

Нека да разгледаме как можем да проверим дали определен порт е свободен или зает с помощта на java.net API.

2.1. S СПЕЦИФИЧНИ Port

Ще използваме класа ServerSocket от API на java.net, за да създадем сокет за сървър, обвързан с посочения порт. В своята конструктор , на ServerSocket приема изричен номер порт. Класът също така изпълнява интерфейса Closeable , така че може да се използва в try-with-resources за автоматично затваряне на сокета и освобождаване на порта:

try (ServerSocket serverSocket = new ServerSocket(FREE_PORT_NUMBER)) { assertThat(serverSocket).isNotNull(); assertThat(serverSocket.getLocalPort()).isEqualTo(FREE_PORT_NUMBER); } catch (IOException e) { fail("Port is not available"); }

В случай, че два пъти използваме определен порт или той вече е зает от друго приложение, конструкторът ServerSocket ще изхвърли IOException :

try (ServerSocket serverSocket = new ServerSocket(FREE_PORT_NUMBER)) { new ServerSocket(FREE_PORT_NUMBER); fail("Same port cannot be used twice"); } catch (IOException e) { assertThat(e).hasMessageContaining("Address already in use"); }

2.2. Обхват на P ort

Нека сега проверим как можем да използваме хвърления IOException, за да създадем сокет за сървър, използвайки първия свободен порт от даден диапазон от номера на портове:

for (int port : FREE_PORT_RANGE) { try (ServerSocket serverSocket = new ServerSocket(port)) { assertThat(serverSocket).isNotNull(); assertThat(serverSocket.getLocalPort()).isEqualTo(port); return; } catch (IOException e) { assertThat(e).hasMessageContaining("Address already in use"); } } fail("No free port in the range found");

3. Намиране на безплатен порт

Използването на изричен номер на порт не винаги е добър вариант, така че нека разгледаме възможностите за автоматично разпределяне на свободен порт.

3.1. Обикновена Java

Можем да използваме специален номер на порт нула в конструктора на клас ServerSocket . В резултат на това API на java.net автоматично ще разпредели безплатен порт за нас:

try (ServerSocket serverSocket = new ServerSocket(0)) { assertThat(serverSocket).isNotNull(); assertThat(serverSocket.getLocalPort()).isGreaterThan(0); } catch (IOException e) { fail("Port is not available"); }

3.2. Пролетна рамка

Spring framework съдържа клас SocketUtils, който можем да използваме, за да намерим наличен безплатен порт. Вътрешната му реализация използва клас ServerSocket , както е показано в предишните ни примери:

int port = SocketUtils.findAvailableTcpPort(); try (ServerSocket serverSocket = new ServerSocket(port)) { assertThat(serverSocket).isNotNull(); assertThat(serverSocket.getLocalPort()).isEqualTo(port); } catch (IOException e) { fail("Port is not available"); }

4. Други реализации на сървъра

Нека сега разгледаме някои други популярни сървърни реализации.

4.1. Пристанище

Jetty е много популярен вграден сървър за Java приложения. Тя автоматично ще се разпределят свободно пристанище за нас, ако не го зададете изрично чрез setPort метода на ServerConnector класа:

Server jettyServer = new Server(); ServerConnector serverConnector = new ServerConnector(jettyServer); jettyServer.addConnector(serverConnector); try { jettyServer.start(); assertThat(serverConnector.getLocalPort()).isGreaterThan(0); } catch (Exception e) { fail("Failed to start Jetty server"); } finally { jettyServer.stop(); jettyServer.destroy(); }

4.2. Tomcat

Tomcat, друг популярен Java вграден сървър, работи малко по-различно. Можем да посочим изричен номер на порт чрез метода setPort на класа Tomcat . В случай, че предоставим номер на порт нула, Tomcat автоматично ще разпредели свободен порт. Ако обаче не зададем никакъв номер на порт, Tomcat ще използва своя порт по подразбиране 8080. Имайте предвид, че портът по подразбиране Tomcat може да бъде зает от други приложения:

Tomcat tomcatServer = new Tomcat(); tomcatServer.setPort(0); try { tomcatServer.start(); assertThat(tomcatServer.getConnector().getLocalPort()).isGreaterThan(0); } catch (LifecycleException e) { fail("Failed to start Tomcat server"); } finally { tomcatServer.stop(); tomcatServer.destroy(); }

5. Заключение

В тази статия разгледахме как да проверим конкретно състояние на порта. Също така разгледахме намирането на безплатен порт от редица номера на портове и обяснихме как да използваме автоматично разпределен безплатен порт.

В примерите покрихме основния клас ServerSocket от API на java.net и други популярни сървърни реализации, включително Jetty и Tomcat.

Както винаги, пълният изходен код е достъпен в GitHub.