¿Cómo determino programáticamente la disponibilidad de un puerto en una máquina dada usando Java?
es decir, dado un número de puerto, determinar si ya se está utilizando o no?
¿Cómo determino programáticamente la disponibilidad de un puerto en una máquina dada usando Java?
es decir, dado un número de puerto, determinar si ya se está utilizando o no?
Respuestas:
Esta es la implementación proveniente del proyecto Camel de Apache :
/**
* Checks to see if a specific port is available.
*
* @param port the port to check for availability
*/
public static boolean available(int port) {
if (port < MIN_PORT_NUMBER || port > MAX_PORT_NUMBER) {
throw new IllegalArgumentException("Invalid start port: " + port);
}
ServerSocket ss = null;
DatagramSocket ds = null;
try {
ss = new ServerSocket(port);
ss.setReuseAddress(true);
ds = new DatagramSocket(port);
ds.setReuseAddress(true);
return true;
} catch (IOException e) {
} finally {
if (ds != null) {
ds.close();
}
if (ss != null) {
try {
ss.close();
} catch (IOException e) {
/* should not be thrown */
}
}
}
return false;
}
También están verificando el DatagramSocket para verificar si el puerto está disponible en UDP y TCP.
Espero que esto ayude.
ServerSocket
puerto de escucha, eso es lo que debe hacer y devolver el ServerSocket
. Crearlo y luego cerrarlo y devolverlo proporciona cero garantía de que se ServerSocket
pueda crear un subsiguiente usando ese puerto. Lo mismo para DatagramSocket
.
Para Java 7, puede usar try-with-resource para obtener un código más compacto:
private static boolean available(int port) {
try (Socket ignored = new Socket("localhost", port)) {
return false;
} catch (IOException ignored) {
return true;
}
}
ConnectException: 'connection refused'
sí, debería devolver falso. Para los tiempos de espera, nada de lo que podría devolver sería válido, ya que no se conoce la respuesta real. Es por eso que esta técnica es inútil para este propósito.
Parece que a partir de Java 7, la respuesta de David Santamaria ya no funciona de manera confiable. Sin embargo, parece que aún puede usar un Socket de manera confiable para probar la conexión.
private static boolean available(int port) {
System.out.println("--------------Testing port " + port);
Socket s = null;
try {
s = new Socket("localhost", port);
// If the code makes it this far without an exception it means
// something is using the port and has responded.
System.out.println("--------------Port " + port + " is not available");
return false;
} catch (IOException e) {
System.out.println("--------------Port " + port + " is available");
return true;
} finally {
if( s != null){
try {
s.close();
} catch (IOException e) {
throw new RuntimeException("You should handle this error." , e);
}
}
}
}
Si no le preocupa demasiado el rendimiento, siempre puede intentar escuchar en un puerto utilizando la clase ServerSocket . Si arroja una excepción, es probable que se esté utilizando.
public static boolean isAvailable(int portNr) {
boolean portFree;
try (var ignored = new ServerSocket(portNr)) {
portFree = true;
} catch (IOException e) {
portFree = false;
}
return portFree;
}
EDITAR: si todo lo que intenta hacer es seleccionar un puerto libre new ServerSocket(0)
, encontrará uno para usted.
La siguiente solución está inspirada en la implementación SocketUtils de Spring-core (licencia de Apache).
En comparación con otras soluciones, su uso Socket(...)
es bastante rápido (prueba de 1000 puertos TCP en menos de un segundo):
public static boolean isTcpPortAvailable(int port) {
try (ServerSocket serverSocket = new ServerSocket()) {
// setReuseAddress(false) is required only on OSX,
// otherwise the code will not work correctly on that platform
serverSocket.setReuseAddress(false);
serverSocket.bind(new InetSocketAddress(InetAddress.getByName("localhost"), port), 1);
return true;
} catch (Exception ex) {
return false;
}
}
Las soluciones basadas en sockets try / catch pueden no producir resultados precisos (la dirección del socket es "localhost" y en algunos casos el puerto podría estar "ocupado" no por la interfaz de bucle invertido y al menos en Windows he visto que esta prueba falla, es decir el prot falsamente declarado como disponible).
Hay una biblioteca genial llamada SIGAR , el siguiente código puede conectarte:
Sigar sigar = new Sigar();
int flags = NetFlags.CONN_TCP | NetFlags.CONN_SERVER | NetFlags.CONN_CLIENT; NetConnection[] netConnectionList = sigar.getNetConnectionList(flags);
for (NetConnection netConnection : netConnectionList) {
if ( netConnection.getLocalPort() == port )
return false;
}
return true;
Una limpieza de la respuesta señalada por David Santamaría:
/**
* Check to see if a port is available.
*
* @param port
* the port to check for availability.
*/
public static boolean isPortAvailable(int port) {
try (var ss = new ServerSocket(port); var ds = new DatagramSocket(port)) {
return true;
} catch (IOException e) {
return false;
}
}
Esto todavía está sujeto a una condición de carrera señalada por el usuario207421 en los comentarios a la respuesta de David Santamaria (algo podría tomar el puerto después de que este método cierre el ServerSocket
y DatagramSocket
y regrese).
En mi caso, ayudó a intentar conectarse al puerto; si el servicio ya está presente, respondería.
try {
log.debug("{}: Checking if port open by trying to connect as a client", portNumber);
Socket sock = new Socket("localhost", portNumber);
sock.close();
log.debug("{}: Someone responding on port - seems not open", portNumber);
return false;
} catch (Exception e) {
if (e.getMessage().contains("refused")) {
return true;
}
log.error("Troubles checking if port is open", e);
throw new RuntimeException(e);
}
En mi caso tuve que usar la clase DatagramSocket.
boolean isPortOccupied(int port) {
DatagramSocket sock = null;
try {
sock = new DatagramSocket(port);
sock.close();
return false;
} catch (BindException ignored) {
return true;
} catch (SocketException ex) {
System.out.println(ex);
return true;
}
}
No olvides importar primero
import java.net.DatagramSocket;
import java.net.BindException;
import java.net.SocketException;
He intentado algo como esto y funcionó muy bien conmigo
Socket Skt;
String host = "localhost";
int i = 8983; // port no.
try {
System.out.println("Looking for "+ i);
Skt = new Socket(host, i);
System.out.println("There is a Server on port "
+ i + " of " + host);
}
catch (UnknownHostException e) {
System.out.println("Exception occured"+ e);
}
catch (IOException e) {
System.out.println("port is not used");
}