Bien que cette question porte sur la façon de savoir si un port donné est déjà utilisé, vous avez peut-être atterri ici en essayant de trouver un moyen d'obtenir un numéro de port gratuit, qui stackoverflow.com/questions/2675362/… (avec un lien vers mon essence .github.com / 3429822 ) couvre mieux.
vorburger
Dans quel but? Si vous voulez juste trouver une socket libre à écouter, spécifiez simplement zéro. Toute technique de numérisation est sujette à des problèmes de fenêtre de synchronisation: le port peut être vacant lorsque vous scannez et occupé lorsque vous allez réclamer.
/**
* 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;}
Ils vérifient également le DatagramSocket pour vérifier si le port est disponible en UDP et TCP.
Une variante intéressante de ceci si vous avez MINA est AvailablePortFinder.getNextAvailable (1024) qui vous donne le prochain port non privilégié.
Alain O'Dea le
9
Cela ne comprend cependant pas tout. J'ai été mordu par un nginx en cours d'exécution sur TCP 8000 alors que la routine ci-dessus signale 8000 comme disponible. Je ne sais pas pourquoi - je soupçonne que nginx fait des trucs sournois (c'est sur OS X). La solution de contournement pour moi est de faire ce qui précède et aussi d'ouvrir un nouveau Socket ("localhost", port) puis de retourner false si nous n'obtenons pas d'exception. Pensées?
Partiellement nuageux le
2
Même problème sur Windows essayant de détecter si le serveur SMTP de papercut est en cours d'exécution. Une solution où vous ouvrez une connexion à un port, plutôt que d'essayer de vous lier à un it (comme suggéré par le commentaire de Partly Clodys et la réponse d'Ivan) semble fonctionner plus fiable.
stian
4
Intéressant. L'appel à setReuseAddress () est complètement inutile une fois que le socket est déjà lié, et il est également complètement contraire à l'objectif du code.
Marquis of Lorne
3
Ce code est sujet à des problèmes de fenêtre de synchronisation. Si l'objectif est de créer une 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 ServerSocketpuisse être créé en utilisant ce port. Idem pour DatagramSocket.
Marquis of Lorne
41
Pour Java 7, vous pouvez utiliser try-with-resource pour un code plus compact:
Cela ne teste pas si le port est disponible. Il teste s'il est à l'état LISTEN, si l'adresse IP est accessible, etc.
Marquis of Lorne
1
De plus, ce test est assez lent (près d'une seconde par port).
JMax
ne devrait-il pas retourner false lorsqu'une IOException est interceptée?
Baroudi Safwen
@BaroudiSafwen Cela dépend entièrement de ce qu'est réellement l'exception. Car 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.
Marquis of Lorne
36
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.
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);}}}}
Je veux vérifier si un serveur proxy est disponible pour passer des appels en son nom.
Dejell
1
La réponse de @ DavidSantamaria n'a jamais fonctionné. Rien à voir avec Java 7.
Marquis of Lorne
35
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é.
Utilisez finally pour le nettoyage (essayez {...} catch {...} finally {if (socket! = Null) socket.close ();}
Hosam Aly
Vous pouvez également définir "portTaken = (socket == null);" à la fin au lieu de le faire dans la capture.
Hosam Aly
1
Je n'ai pas pensé que cela entrait dans le cadre de la question de l'auteur.
Spencer Ruport
1
Y a-t-il un moyen de le faire sans essayer / attraper? Cela ne me dérangerait pas d'utiliser n'importe quel port disponible à mes fins, mais itérer sur les numéros de port et essayer / attraper chacun jusqu'à ce que je trouve un port gratuit est un peu inutile. N'y a-t-il pas quelque part une méthode 'native boolean available (int)', qui vérifie simplement?
Oren Shalev
27
new SeverSocket (0) sélectionnera automatiquement un port libre.
Spencer Ruport
10
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):
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;}}
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:
J'obtiens: "pas de sigar-x86-winnt.dll dans java.library.path" Malheureusement, cela nécessite le téléchargement d'une DLL supplémentaire qui n'est pas vraiment viable dans l'environnement d'entreprise (je n'ai aucun contrôle sur le système CI). Tellement mauvais ... Merci quand même.
uthomas
@uthomas Je suppose que vous avez toujours le contrôle sur le package de déploiement de votre application, si tel est le cas, vous pouvez toujours fournir des DLL / SO d'exécution natives Sigar à proximité de vos JAR et définir le chemin de la bibliothèque JAVA de manière pragmatique (via un simple hack, vous pouvez l'influencer même après votre app a été lancée par la JVM).
Shmil The Cat
2
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.
*/publicstaticboolean isPortAvailable(int port){try(var ss =newServerSocket(port); var ds =newDatagramSocket(port)){returntrue;}catch(IOException e){returnfalse;}}
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 ServerSocketet DatagramSocketet 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 =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);}
Cela fonctionne pour les ports UDP. La question semble concerner les ports TCP.
Marquis of Lorne
-2
J'ai essayé quelque chose comme ça et ça a très bien fonctionné avec moi
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");}
Réponses:
Voici l' implémentation issue du projet Apache camel :
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.
la source
ServerSocket
écoute sur un port, c'est ce qu'il doit faire et renvoyer le fichierServerSocket
. Le créer puis le fermer et le renvoyer ne fournit aucune garantie qu'un suivantServerSocket
puisse être créé en utilisant ce port. Idem pourDatagramSocket
.Pour Java 7, vous pouvez utiliser try-with-resource pour un code plus compact:
la source
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.
la source
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é.
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 source
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):la source
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:
la source
Un nettoyage de la réponse soulignée par David Santamaria:
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
etDatagramSocket
et retourne).la source
Dans mon cas, cela a aidé à essayer de se connecter au port - si le service est déjà présent, il répondrait.
la source
Dans mon cas, j'ai dû utiliser la classe DatagramSocket.
N'oubliez pas d'importer d'abord
la source
J'ai essayé quelque chose comme ça et ça a très bien fonctionné avec moi
la source