Recherche d'un port gratuit à Java

1. Vue d'ensemble

Lors du démarrage d'un serveur socket dans notre application Java, l' API java.net nous oblige à spécifier un numéro de port libre à écouter. Le numéro de port est requis pour que la couche TCP puisse identifier l'application à laquelle les données entrantes sont destinées.

La spécification explicite d'un numéro de port n'est pas toujours une bonne option, car les applications peuvent déjà l'occuper. Cela provoquera une exception d'entrée / sortie dans notre application Java.

Dans ce rapide tutoriel, nous verrons comment vérifier un état de port spécifique et comment utiliser un état alloué automatiquement. Nous verrons comment cela peut être fait avec un framework Java et Spring. Nous examinerons également d'autres implémentations de serveur, telles que Tomcat et Jetty intégrés.

2. Vérification de l'état du port

Voyons comment nous pouvons vérifier si un port spécifique est libre ou occupé à l'aide de l' API java.net .

2.1. Port S pécifique

Nous utiliserons la classe ServerSocket de l' API java.net pour créer un socket serveur, lié au port spécifié. Dans son constructeur , le ServerSocket accepte un numéro de port explicite. La classe implémente également l' interface Closeable , afin qu'elle puisse être utilisée dans try-with-resources pour fermer automatiquement le socket et libérer le port:

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

Dans le cas où nous utilisons un port spécifique deux fois, ou s'il est déjà occupé par une autre application, le constructeur ServerSocket lèvera une 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. Gamme de P ort

Voyons maintenant comment nous pouvons utiliser l' exception IOException lancée , pour créer un socket serveur en utilisant le premier port libre d'une plage donnée de numéros de port:

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. Recherche d' un port gratuit

Utiliser un numéro de port explicite n'est pas toujours une bonne option, alors examinons les possibilités d'allouer automatiquement un port libre.

3.1. Java simple

Nous pouvons utiliser un numéro de port spécial zéro dans le constructeur de classe ServerSocket . En conséquence, l' API java.net nous attribuera automatiquement un port gratuit:

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

3.2. Cadre de printemps

Le framework Spring contient une classe SocketUtils que nous pouvons utiliser pour trouver un port libre disponible. Son implémentation interne utilise la classe ServerSocket , comme indiqué dans nos exemples précédents:

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. Autres implémentations de serveur

Jetons maintenant un coup d'œil à d'autres implémentations de serveur populaires.

4.1. Jetée

Jetty est un serveur intégré très populaire pour les applications Java. Il nous allouera automatiquement un port libre à moins que nous ne le définissions explicitement via la méthode setPort de la classe 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. Matou

Tomcat, un autre serveur intégré Java populaire, fonctionne un peu différemment. Nous pouvons spécifier un numéro de port explicite via la méthode setPort de la classe Tomcat . Si nous fournissons un numéro de port zéro, Tomcat attribuera automatiquement un port libre. Cependant, si nous ne définissons aucun numéro de port, Tomcat utilisera son port par défaut 8080. Notez que le port Tomcat par défaut pourrait être occupé par d'autres applications:

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

Dans cet article, nous avons exploré comment vérifier l'état d'un port spécifique. Nous avons également couvert la recherche d'un port gratuit à partir d'une gamme de numéros de port et expliqué comment utiliser un port gratuit alloué automatiquement.

Dans les exemples, nous avons couvert la classe de base ServerSocket de l' API java.net et d'autres implémentations de serveur populaires, notamment Jetty et Tomcat.

Comme toujours, le code source complet est disponible à l'adresse over sur GitHub.