Een vrije poort zoeken in Java

1. Overzicht

Bij het starten van een socketserver in onze Java-applicatie, de java.net API vereist dat we een vrij poortnummer specificeren om naar te luisteren. Het poortnummer is vereist zodat de TCP-laag de toepassing kan identificeren waarvoor de inkomende gegevens bedoeld zijn.

Het expliciet specificeren van een poortnummer is niet altijd een goede optie, omdat het mogelijk al bezet is door applicaties. Dit veroorzaakt een invoer / uitvoer-uitzondering in onze Java-applicatie.

In deze korte handleiding bekijken we hoe u een specifieke poortstatus kunt controleren en hoe u een automatisch toegewezen poort kunt gebruiken. We zullen onderzoeken hoe dit kan worden gedaan met een gewoon Java- en Spring-framework. We zullen ook kijken naar enkele andere serverimplementaties, zoals embedded Tomcat en Jetty.

2. De poortstatus controleren

Laten we eens kijken hoe we kunnen controleren of een specifieke poort vrij of bezet is met behulp van de java.net API.

2.1. Sspecifieke poort

We maken gebruik van de ServerSocket klasse uit de java.net API om een ​​server-socket te maken, gebonden aan de opgegeven poort. In zijn constructor, de ServerSocket accepteert een expliciet poortnummer. De klasse implementeert ook het Afsluitbaar interface, zodat het kan worden gebruikt in probeer-met-middelen om het stopcontact automatisch te sluiten en de poort vrij te maken:

probeer (ServerSocket serverSocket = nieuwe ServerSocket (FREE_PORT_NUMBER)) {assertThat (serverSocket) .isNotNull (); assertThat (serverSocket.getLocalPort ()). isEqualTo (FREE_PORT_NUMBER); } catch (IOException e) {fail ("Poort is niet beschikbaar"); }

In het geval dat we een specifieke poort twee keer gebruiken, of deze al bezet is door een andere applicatie, kan het ServerSocket constructor zal een IOException:

probeer (ServerSocket serverSocket = nieuwe ServerSocket (FREE_PORT_NUMBER)) {nieuwe ServerSocket (FREE_PORT_NUMBER); fail ("Dezelfde poort kan niet twee keer worden gebruikt"); } catch (IOException e) {assertThat (e) .hasMessageContaining ("Adres al in gebruik"); }

2.2. P.ort Bereik

Laten we nu kijken hoe we gebruik kunnen maken van de throw IOException, om een ​​server-socket te maken met behulp van de eerste vrije poort uit een bepaald bereik van poortnummers:

voor (int poort: FREE_PORT_RANGE) {probeer (ServerSocket serverSocket = nieuwe ServerSocket (poort)) {assertThat (serverSocket) .isNotNull (); assertThat (serverSocket.getLocalPort ()). isEqualTo (poort); terugkeren; } catch (IOException e) {assertThat (e) .hasMessageContaining ("Adres al in gebruik"); }} mislukt ("Geen vrije poort in het bereik gevonden");

3. Vinden een vrije poort

Het gebruik van een expliciet poortnummer is niet altijd een goede optie, dus laten we eens kijken naar de mogelijkheden om automatisch een vrije poort toe te wijzen.

3.1. Gewoon Java

We kunnen een speciaal poortnummer nul gebruiken in de ServerSocket klasse constructor. Als gevolg hiervan is het java.net API wijst automatisch een vrije poort voor ons toe:

probeer (ServerSocket serverSocket = nieuwe ServerSocket (0)) {assertThat (serverSocket) .isNotNull (); assertThat (serverSocket.getLocalPort ()). isGreaterThan (0); } catch (IOException e) {fail ("Poort is niet beschikbaar"); }

3.2. Spring Framework

Spring framework bevat een SocketUtils klasse die we kunnen gebruiken om een ​​beschikbare vrije poort te vinden. De interne implementatie maakt gebruik van de ServerSocket class, zoals getoond in onze vorige voorbeelden:

int port = SocketUtils.findAvailableTcpPort (); probeer (ServerSocket serverSocket = nieuwe ServerSocket (poort)) {assertThat (serverSocket) .isNotNull (); assertThat (serverSocket.getLocalPort ()). isEqualTo (poort); } catch (IOException e) {fail ("Poort is niet beschikbaar"); }

4. Andere serverimplementaties

Laten we nu eens kijken naar enkele andere populaire serverimplementaties.

4.1. Steiger

Jetty is een zeer populaire embedded server voor Java-applicaties. Het wijst automatisch een vrije poort voor ons toe, tenzij we dit expliciet instellen via het setPort methode van de ServerConnector klasse:

Server jettyServer = nieuwe server (); ServerConnector serverConnector = nieuwe ServerConnector (jettyServer); jettyServer.addConnector (serverConnector); probeer {jettyServer.start (); assertThat (serverConnector.getLocalPort ()). isGreaterThan (0); } catch (uitzondering e) {fail ("Starten van Jetty-server is mislukt"); } eindelijk {jettyServer.stop (); jettyServer.destroy (); }

4.2. Kater

Tomcat, een andere populaire ingebedde Java-server, werkt een beetje anders. We kunnen een expliciet poortnummer specificeren via de setPort methode van de Kater klasse. Als we poortnummer nul opgeven, wijst Tomcat automatisch een vrije poort toe. Als we echter geen poortnummer instellen, zal Tomcat de standaardpoort 8080 gebruiken. Merk op dat de standaard Tomcat-poort bezet kan zijn door andere toepassingen:

Tomcat tomcatServer = nieuwe Tomcat (); tomcatServer.setPort (0); probeer {tomcatServer.start (); assertThat (tomcatServer.getConnector (). getLocalPort ()). isGreaterThan (0); } catch (LifecycleException e) {fail ("Starten van Tomcat-server is mislukt"); } eindelijk {tomcatServer.stop (); tomcatServer.destroy (); }

5. Conclusie

In dit artikel hebben we onderzocht hoe u een specifieke poortstatus kunt controleren. We bespraken ook het vinden van een vrije poort uit een reeks poortnummers en legden uit hoe je een automatisch toegewezen vrije poort kunt gebruiken.

In de voorbeelden hebben we de basis behandeld ServerSocket klasse uit de java.net API en andere populaire serverimplementaties, waaronder Jetty en Tomcat.

Zoals altijd is de volledige broncode beschikbaar op GitHub.