Comment déterminer par programme la disponibilité d'un port sur une machine donnée à l'aide de Java?
ie étant donné un numéro de port, déterminer s'il est déjà utilisé ou non ?.
Comment déterminer par programme la disponibilité d'un port sur une machine donnée à l'aide de Java?
ie étant donné un numéro de port, déterminer s'il est déjà utilisé ou non ?.
Réponses:
Voici l' implémentation issue du projet Apache camel :
/**
* 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;
}
Ils vérifient également le DatagramSocket pour vérifier si le port est disponible en UDP et TCP.
J'espère que cela t'aides.
ServerSocket
écoute sur un port, c'est ce qu'il doit faire et renvoyer le fichier ServerSocket
. Le créer puis le fermer et le renvoyer ne fournit aucune garantie qu'un suivant ServerSocket
puisse être créé en utilisant ce port. Idem pour DatagramSocket
.
Pour Java 7, vous pouvez utiliser try-with-resource pour un code plus compact:
private static boolean available(int port) {
try (Socket ignored = new Socket("localhost", port)) {
return false;
} catch (IOException ignored) {
return true;
}
}
ConnectException: 'connection refused'
, oui, il devrait renvoyer false. Pour les délais d'attente, rien de ce qu'il pourrait renvoyer ne serait valide, car la réponse réelle n'est pas connue. C'est pourquoi cette technique est inutile à cet effet.
Il semble qu'à partir de Java 7, la réponse de David Santamaria ne fonctionne plus de manière fiable. Il semble cependant que vous puissiez toujours utiliser de manière fiable un socket pour tester la connexion.
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 vous n'êtes pas trop préoccupé par les performances, vous pouvez toujours essayer d'écouter sur un port à l'aide de la classe ServerSocket . S'il lève une exception, il y a des chances qu'il soit utilisé.
public static boolean isAvailable(int portNr) {
boolean portFree;
try (var ignored = new ServerSocket(portNr)) {
portFree = true;
} catch (IOException e) {
portFree = false;
}
return portFree;
}
EDIT: Si tout ce que vous essayez de faire est de sélectionner un port libre, new ServerSocket(0)
vous en trouverez un pour vous.
La solution suivante est inspirée de l' implémentation SocketUtils de Spring-core (licence Apache).
Par rapport aux autres solutions qui l'utilisent, Socket(...)
c'est assez rapide (tester 1000 ports TCP en moins d'une seconde):
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;
}
}
Les solutions basées sur le socket try / catch peuvent ne pas donner des résultats précis (l'adresse du socket est "localhost" et dans certains cas, le port peut être "occupé" non par l'interface de bouclage et au moins sur Windows, j'ai vu ce test échouer, c'est-à-dire le prot déclaré à tort comme disponible).
Il existe une bibliothèque sympa nommée SIGAR , le code suivant peut vous connecter:
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;
Un nettoyage de la réponse soulignée par David Santamaria:
/**
* 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;
}
}
Ceci est toujours soumis à une condition de concurrence signalée par user207421 dans les commentaires de la réponse de David Santamaria (quelque chose pourrait saisir le port après que cette méthode ferme le ServerSocket
et DatagramSocket
et retourne).
Dans mon cas, cela a aidé à essayer de se connecter au port - si le service est déjà présent, il répondrait.
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);
}
Dans mon cas, j'ai dû utiliser la classe 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;
}
}
N'oubliez pas d'importer d'abord
import java.net.DatagramSocket;
import java.net.BindException;
import java.net.SocketException;
J'ai essayé quelque chose comme ça et ça a très bien fonctionné avec moi
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");
}