Einen freien Port in Java finden

1. Übersicht

Beim Starten eines Socket-Servers in unserer Java-Anwendung müssen wir für die java.net- API eine freie Portnummer angeben , die abgehört werden soll . Die Portnummer ist erforderlich, damit die TCP-Schicht die Anwendung identifizieren kann, für die die eingehenden Daten bestimmt sind.

Die explizite Angabe einer Portnummer ist nicht immer eine gute Option, da Anwendungen sie möglicherweise bereits belegen. Dies führt zu einer Eingabe- / Ausgabeausnahme in unserer Java-Anwendung.

In diesem kurzen Tutorial erfahren Sie, wie Sie einen bestimmten Portstatus überprüfen und einen automatisch zugewiesenen verwenden. Wir werden untersuchen, wie dies mit einfachem Java- und Spring-Framework erreicht werden kann. Wir werden uns auch einige andere Serverimplementierungen ansehen, wie eingebettetes Tomcat und Jetty.

2. Überprüfen des Portstatus

Schauen wir uns an, wie wir mithilfe der java.net- API überprüfen können, ob ein bestimmter Port frei oder belegt ist .

2.1. S pecific Hafen

Wir werden die ServerSocket- Klasse aus der java.net- API verwenden, um einen Server-Socket zu erstellen, der an den angegebenen Port gebunden ist. In seinem Konstruktor akzeptiert der ServerSocket eine explizite Portnummer. Die Klasse implementiert auch die Closeable- Schnittstelle, sodass sie in Try-with-Resources verwendet werden kann , um den Socket automatisch zu schließen und den Port freizugeben :

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

Wenn wir einen bestimmten Port zweimal verwenden oder dieser bereits von einer anderen Anwendung belegt ist, löst der ServerSocket- Konstruktor eine IOException aus :

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 Bereich

Lassen Sie uns nun überprüfen, wie wir die ausgelöste IOException verwenden können , um einen Server-Socket mit dem ersten freien Port aus einem bestimmten Bereich von Portnummern zu erstellen:

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. Einen freien Port finden

Die Verwendung einer expliziten Portnummer ist nicht immer eine gute Option. Schauen wir uns daher die Möglichkeiten an, einen freien Port automatisch zuzuweisen.

3.1. Einfaches Java

Wir können eine spezielle Portnummer Null im ServerSocket- Klassenkonstruktor verwenden. Infolgedessen weist uns die java.net- API automatisch einen freien Port zu:

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

3.2. Frühlingsrahmen

Das Spring Framework enthält eine SocketUtils- Klasse, mit der wir einen verfügbaren freien Port finden können. Die interne Implementierung verwendet die ServerSocket- Klasse, wie in unseren vorherigen Beispielen gezeigt:

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. Andere Serverimplementierungen

Schauen wir uns nun einige andere beliebte Serverimplementierungen an.

4.1. Steg

Jetty ist ein sehr beliebter Embedded-Server für Java-Anwendungen. Es wird automatisch ein freier Port für uns zugewiesen, es sei denn, wir legen ihn explizit über die setPort- Methode der ServerConnector- Klasse fest:

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. Kater

Tomcat, ein weiterer beliebter Java Embedded Server, funktioniert etwas anders. Wir können eine explizite Portnummer über die setPort- Methode der Tomcat- Klasse angeben . Wenn wir eine Portnummer Null angeben, weist Tomcat automatisch einen freien Port zu. Wenn wir jedoch keine Portnummer festlegen, verwendet Tomcat den Standardport 8080. Beachten Sie, dass der Standard-Tomcat-Port möglicherweise von anderen Anwendungen belegt wird:

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. Schlussfolgerung

In diesem Artikel haben wir untersucht, wie Sie einen bestimmten Portstatus überprüfen. Wir haben auch die Suche nach einem freien Port aus einer Reihe von Portnummern behandelt und erklärt, wie ein automatisch zugewiesener freier Port verwendet wird.

In den Beispielen haben wir die grundlegende ServerSocket- Klasse aus der java.net- API und anderen gängigen Serverimplementierungen , einschließlich Jetty und Tomcat, behandelt.

Wie immer ist der vollständige Quellcode auf GitHub verfügbar.