1. Overview
When starting a socket server in our Java application, the java.net API requires us to specify a free port number to listen on. The port number is required so that the TCP layer can identify the application that the incoming data is intended for.
Specifying a port number explicitly is not always a good option, because applications might already occupy it. This will cause an input/output exception in our Java application.
In this quick tutorial, we’ll look at how to check a specific port status and how to use an automatically allocated one. We’ll look into how this can be done with plain Java and Spring framework. We’ll also look at some other server implementations, like embedded Tomcat and Jetty.
2. Checking Port Status
Let’s look at how we can check if a specific port is free or occupied using the java.net API.
2.1. Specific Port
We’ll make use of the ServerSocket class from the java.net API to create a server socket, bound to the specified port. In its constructor, the ServerSocket accepts an explicit port number. The class also implements the Closeable interface, so it can be used in try-with-resources to automatically close the socket and free up the 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");
}
In case we use a specific port twice, or it’s already occupied by another application, the ServerSocket constructor will throw an 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. Port Range
Let’s now check how we can make use of the thrown IOException, to create a server socket using the first free port from a given range of port numbers:
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. Finding a Free Port
Using an explicit port number is not always a good option, so let’s look into possibilities to allocate a free port automatically.
3.1. Plain Java
We can use a special port number zero in the ServerSocket class constructor. As a result, the java.net API will automatically allocate a free port for us:
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
Spring framework contains a SocketUtils class that we can use to find an available free port. Its internal implementation uses the ServerSocket class, as shown in our previous examples:
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. Other Server Implementations
Let’s now take a look at some other popular server implementations.
4.1. Jetty
Jetty is a very popular embedded server for Java applications. It will automatically allocate a free port for us unless we set it explicitly via the setPort method of the ServerConnector class:
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, another popular Java embedded server, works a bit differently. We can specify an explicit port number via the setPort method of the Tomcat class. In case we provide a port number zero, Tomcat will automatically allocate a free port. However, if we don’t set any port number, Tomcat will use its default port 8080. Note that the default Tomcat port could be occupied by other 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
In this article, we explored how to check a specific port status. We also covered finding a free port from a range of port numbers and explained how to use an automatically allocated free port.
In the examples, we covered the basic ServerSocket class from the java.net API and other popular server implementations, including Jetty and Tomcat.
As always, the complete source code is available over on GitHub.