Si bien esta pregunta es sobre cómo saber si un puerto dado ya está en uso, es posible que haya aterrizado aquí tratando de encontrar una manera de obtener un número de puerto gratuito, que stackoverflow.com/questions/2675362/… (con enlace a mi esencia) .github.com / 3429822 ) cubre mejor.
vorburger
¿Con qué propósito? Si solo desea encontrar un socket vacío para escuchar, especifique cero. Cualquier técnica de escaneo es susceptible a problemas de ventana de tiempo: el puerto puede estar vacante cuando escanea y ocupado cuando va a reclamar.
/**
* Checks to see if a specific port is available.
*
* @param port the port to check for availability
*/publicstaticboolean available(int port){if(port < MIN_PORT_NUMBER || port > MAX_PORT_NUMBER){thrownewIllegalArgumentException("Invalid start port: "+ port);}ServerSocket ss =null;DatagramSocket ds =null;try{
ss =newServerSocket(port);
ss.setReuseAddress(true);
ds =newDatagramSocket(port);
ds.setReuseAddress(true);returntrue;}catch(IOException e){}finally{if(ds !=null){
ds.close();}if(ss !=null){try{
ss.close();}catch(IOException e){/* should not be thrown */}}}returnfalse;}
También están verificando el DatagramSocket para verificar si el puerto está disponible en UDP y TCP.
Una buena variante de esto si tiene MINA es AvailablePortFinder.getNextAvailable (1024), que le proporciona el siguiente puerto no privilegiado.
Alain O'Dea
9
Sin embargo, esto no atrapa todo. Me ha mordido un nginx en ejecución en TCP 8000, mientras que la rutina anterior informa que 8000 está disponible. No tengo idea de por qué: sospecho que nginx hace algunas cosas furtivas (esto es en OS X). La solución para mí es hacer lo anterior y también abrir un nuevo Socket ("localhost", puerto) y luego devolver false si no obtenemos una excepción. Pensamientos?
Parcialmente nublado
2
El mismo problema en Windows que intenta detectar si se está ejecutando el servidor SMTP papercut. Una solución en la que abres una conexión a un puerto, en lugar de intentar unirte a ella (como sugiere el comentario de Clodys y la respuesta de Ivan) parece funcionar de manera más confiable.
stian
44
Interesante. La llamada a setReuseAddress () es completamente inútil después de que el socket ya está vinculado, y también es completamente contrario al propósito del código.
Marqués de Lorne
3
Este código está sujeto a problemas de ventana de tiempo. Si el objetivo es crear un ServerSocketpuerto 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 ServerSocketpueda crear un subsiguiente usando ese puerto. Lo mismo para DatagramSocket.
Marqués de Lorne
41
Para Java 7, puede usar try-with-resource para obtener un código más compacto:
Esto no prueba si en el puerto está disponible. Comprueba si está en estado ESCUCHAR, si se puede acceder a la dirección IP, etc.
Marqués de Lorne
1
Además, esta prueba es bastante lenta (casi un segundo por puerto).
JMax
¿No debería devolver falso cuando se detecta una IOException?
Baroudi Safwen
@BaroudiSafwen Depende completamente de cuál sea realmente la excepción. Pues 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.
Marqués de Lorne el
36
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.
privatestaticboolean available(int port){System.out.println("--------------Testing port "+ port);Socket s =null;try{
s =newSocket("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");returnfalse;}catch(IOException e){System.out.println("--------------Port "+ port +" is available");returntrue;}finally{if( s !=null){try{
s.close();}catch(IOException e){thrownewRuntimeException("You should handle this error.", e);}}}}
Quiero verificar si hay un servidor proxy disponible para realizar llamadas en su nombre.
Dejell el
1
La respuesta de @DavidSantamaria nunca funcionó. Nada que ver con Java 7.
Marqués de Lorne
35
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.
Úselo finalmente para la limpieza (intente {...} catch {...} finally {if (socket! = Null) socket.close ();}
Hosam Aly
También puede establecer "portTaken = (socket == null);" al final en lugar de hacerlo en la captura.
Hosam Aly
1
No sentí que cayera dentro del alcance previsto de la pregunta del autor.
Spencer Ruport
1
¿Hay alguna manera de hacerlo sin intentar / atrapar? No me importaría usar ningún puerto disponible para mis propósitos, pero iterar sobre los números de puerto e intentar / atrapar cada uno hasta que encuentre uno libre es un poco inútil. ¿No hay un método 'nativo booleano disponible (int)' en alguna parte, que simplemente verifica?
Oren Shalev
27
El nuevo SeverSocket (0) seleccionará automáticamente un puerto libre.
Spencer Ruport
10
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):
publicstaticboolean isTcpPortAvailable(int port){try(ServerSocket serverSocket =newServerSocket()){// setReuseAddress(false) is required only on OSX, // otherwise the code will not work correctly on that platform
serverSocket.setReuseAddress(false);
serverSocket.bind(newInetSocketAddress(InetAddress.getByName("localhost"), port),1);returntrue;}catch(Exception ex){returnfalse;}}
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:
Obtengo: "no sigar-x86-winnt.dll en java.library.path" Desafortunadamente, requiere la descarga de algún dll adicional que no es realmente viable en el entorno empresarial (no tengo control sobre el sistema CI). Tan mal ... Gracias de todos modos.
uthomas
@uthomas Supongo que todavía tiene control sobre el paquete de implementación de la aplicación, si este es el caso, siempre puede proporcionar las DLL / SO nativas de tiempo de ejecución de Sigar cerca de sus JAR y establecer la ruta JAVA lib pragmáticamente (a través de un simple hack puede influir incluso después de su aplicación ha sido lanzada por la JVM).
Shmil The Cat
2
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.
*/publicstaticboolean isPortAvailable(int port){try(var ss =newServerSocket(port); var ds =newDatagramSocket(port)){returntrue;}catch(IOException e){returnfalse;}}
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 ServerSockety DatagramSockety 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 =newSocket("localhost", portNumber);
sock.close();
log.debug("{}: Someone responding on port - seems not open", portNumber);returnfalse;}catch(Exception e){if(e.getMessage().contains("refused")){returntrue;}
log.error("Troubles checking if port is open", e);thrownewRuntimeException(e);}
Esto funciona para puertos UDP. La pregunta parece ser sobre los puertos TCP.
Marqués de Lorne
-2
He intentado algo como esto y funcionó muy bien conmigo
SocketSkt;String host ="localhost";int i =8983;// port no.try{System.out.println("Looking for "+ i);Skt=newSocket(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");}
Respuestas:
Esta es la implementación proveniente del proyecto Camel de Apache :
También están verificando el DatagramSocket para verificar si el puerto está disponible en UDP y TCP.
Espero que esto ayude.
fuente
ServerSocket
puerto de escucha, eso es lo que debe hacer y devolver elServerSocket
. Crearlo y luego cerrarlo y devolverlo proporciona cero garantía de que seServerSocket
pueda crear un subsiguiente usando ese puerto. Lo mismo paraDatagramSocket
.Para Java 7, puede usar try-with-resource para obtener un código más compacto:
fuente
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.
fuente
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.
EDITAR: si todo lo que intenta hacer es seleccionar un puerto libre
new ServerSocket(0)
, encontrará uno para usted.fuente
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):fuente
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:
fuente
Una limpieza de la respuesta señalada por David Santamaría:
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
yDatagramSocket
y regrese).fuente
En mi caso, ayudó a intentar conectarse al puerto; si el servicio ya está presente, respondería.
fuente
En mi caso tuve que usar la clase DatagramSocket.
No olvides importar primero
fuente
He intentado algo como esto y funcionó muy bien conmigo
fuente