Während es bei dieser Frage darum geht, wie Sie feststellen können, ob ein bestimmter Port bereits verwendet wird, sind Sie möglicherweise hier gelandet, um einen Weg zu finden, eine kostenlose Portnummer zu erhalten, die stackoverflow.com/questions/2675362/… (mit Link zu meinem Kern) enthält .github.com / 3429822 ) deckt besser ab.
Vorburger
Für welchen Zweck? Wenn Sie nur einen freien Socket zum Abhören suchen möchten, geben Sie einfach Null an. Jede Scan-Technik unterliegt Zeitfensterproblemen: Der Port kann beim Scannen frei und belegt sein, wenn Sie einen Anspruch geltend machen.
/**
* 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;}
Sie überprüfen auch das DatagramSocket, um zu überprüfen, ob der Port in UDP und TCP verfügbar ist.
Eine nette Variante davon, wenn Sie MINA haben, ist AvailablePortFinder.getNextAvailable (1024), mit dem Sie den nächsten nicht privilegierten Port erhalten.
Alain O'Dea
9
Dies fängt jedoch nicht alles. Ich wurde von einem laufenden Nginx auf TCP 8000 gebissen, während die obige Routine 8000 als verfügbar meldet. Keine Ahnung warum - ich vermute, Nginx macht ein paar hinterhältige Sachen (dies ist unter OS X). Problemumgehung für mich ist, das oben Genannte zu tun und auch einen neuen Socket ("localhost", Port) zu öffnen und dann false zurückzugeben, wenn wir keine Ausnahme erhalten. Gedanken?
Teilweise bewölkt
2
Das gleiche Problem unter Windows, das versucht zu erkennen, ob der SMTP-Server mit Papierschnitt ausgeführt wird. Eine Lösung, bei der Sie eine Verbindung zu einem Port herstellen, anstatt zu versuchen, sich an einen Port zu binden (wie in Partly Clodys Kommentar und Iwans Antwort vorgeschlagen), scheint zuverlässiger zu funktionieren.
Stian
4
Interessant. Der Aufruf von setReuseAddress () ist völlig sinnlos, nachdem der Socket bereits gebunden ist, und widerspricht auch völlig dem Zweck des Codes.
Marquis von Lorne
3
Dieser Code unterliegt Zeitfensterproblemen. Wenn das Ziel darin besteht, einen ServerSocketabhörenden Port zu erstellen , sollte dies der Fall sein und der zurückgegeben werden ServerSocket. Das Erstellen und anschließende Schließen und Zurückgeben bietet keine Garantie dafür, dass ServerSocketüber diesen Port eine nachfolgende erstellt werden kann. Das Gleiche gilt für DatagramSocket.
Marquis von Lorne
41
Für Java 7 können Sie try-with-resource für kompakteren Code verwenden:
Dies testet nicht, ob am Port verfügbar ist. Es testet, ob es sich im LISTEN-Status befindet, ob die IP-Adresse erreichbar ist usw.
Marquis of Lorne
1
Außerdem ist dieser Test ziemlich langsam (fast eine Sekunde pro Port).
JMax
Sollte es nicht false zurückgeben, wenn eine IOException abgefangen wird?
Baroudi Safwen
@ BaroudiSafwen Es hängt ganz davon ab, was die Ausnahme tatsächlich ist. Für ConnectException: 'connection refused', ja sollte es false zurück. Für Zeitüberschreitungen ist nichts gültig, was zurückgegeben werden könnte, da die tatsächliche Antwort nicht bekannt ist. Deshalb ist diese Technik für diesen Zweck nutzlos.
Marquis von Lorne
36
Ab Java 7 scheint die Antwort von David Santamaria nicht mehr zuverlässig zu funktionieren. Es sieht jedoch so aus, als könnten Sie die Verbindung weiterhin zuverlässig mit einem Socket testen.
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);}}}}
Ich möchte überprüfen, ob ein Proxyserver verfügbar ist, um in seinem Namen einen Anruf zu tätigen.
Dejell
1
@ DavidSantamarias Antwort hat nie funktioniert. Nichts mit Java 7 zu tun.
Marquis von Lorne
35
Wenn Sie sich nicht zu sehr mit der Leistung befassen, können Sie jederzeit versuchen, einen Port mit der ServerSocket- Klasse abzuhören . Wenn es eine Ausnahme auslöst, werden die Chancen verwendet.
Verwenden Sie finally für die Bereinigung (versuchen Sie {...} catch {...} finally {if (socket! = Null) socket.close ();}
Hosam Aly
Sie können auch "portTaken = (socket == null);" am Ende anstatt es im Fang zu tun.
Hosam Aly
1
Ich hatte nicht das Gefühl, dass dies in den beabsichtigten Rahmen der Frage des Autors fällt.
Spencer Ruport
1
Gibt es eine Möglichkeit, dies ohne Versuch / Fang zu tun? Es würde mir nichts ausmachen, einen verfügbaren Port für meine Zwecke zu verwenden, aber es ist ein wenig verschwenderisch, über Portnummern zu iterieren und zu versuchen, jeden zu durchsuchen, bis ich einen freien finde. Gibt es nicht irgendwo eine 'native boolean available (int)' Methode, die nur prüft?
Oren Shalev
27
Das neue SeverSocket (0) wählt automatisch einen freien Port aus.
Spencer Ruport
10
Die folgende Lösung ist von der SocketUtils- Implementierung von Spring-Core (Apache-Lizenz) inspiriert .
Im Vergleich zu anderen Lösungen ist die Verwendung Socket(...)ziemlich schnell (Testen von 1000 TCP-Ports in weniger als einer Sekunde):
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;}}
Die auf Try / Catch-Sockets basierenden Lösungen liefern möglicherweise keine genauen Ergebnisse (die Socket-Adresse lautet "localhost", und in einigen Fällen kann der Port nicht von der Loopback-Schnittstelle "belegt" werden, und zumindest unter Windows ist dieser Test fehlgeschlagen, z der Schutz fälschlicherweise als verfügbar deklariert).
Es gibt eine coole Bibliothek namens SIGAR , der folgende Code kann Sie verbinden:
Ich erhalte: "no sigar-x86-winnt.dll in java.library.path" Leider muss eine zusätzliche DLL heruntergeladen werden, die in einer Unternehmensumgebung nicht wirklich realisierbar ist (ich habe keine Kontrolle über das CI-System). So schlimm ... Trotzdem danke.
Uthomas
@uthomas Ich denke, Sie haben immer noch die Kontrolle über Ihr App-Bereitstellungspaket. Wenn dies der Fall ist, können Sie immer native Sigar-Laufzeit-DLLs / SOs in der Nähe Ihrer JARs bereitstellen und den JAVA-Lib-Pfad pragmatisch festlegen (über einen einfachen Hack können Sie ihn auch nach Ihrem ändern App wurde von der JVM gestartet).
Shmil The Cat
2
Eine Bereinigung der Antwort von 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;}}
Dies unterliegt immer noch einer Rennbedingung, auf die user207421 in den Kommentaren zu David Santamarias Antwort hingewiesen hat (etwas könnte den Port greifen, nachdem diese Methode das ServerSocketund geschlossen hat DatagramSocketund zurückkehrt).
In meinem Fall hat es geholfen, eine Verbindung zum Port herzustellen. Wenn der Dienst bereits vorhanden ist, reagiert er.
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);}
Dies funktioniert für UDP-Ports. Die Frage scheint sich auf TCP-Ports zu beziehen.
Marquis von Lorne
-2
Ich habe so etwas ausprobiert und es hat bei mir sehr gut funktioniert
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");}
Antworten:
Dies ist die Implementierung aus dem Apache- Kamelprojekt :
Sie überprüfen auch das DatagramSocket, um zu überprüfen, ob der Port in UDP und TCP verfügbar ist.
Hoffe das hilft.
quelle
ServerSocket
abhörenden Port zu erstellen , sollte dies der Fall sein und der zurückgegeben werdenServerSocket
. Das Erstellen und anschließende Schließen und Zurückgeben bietet keine Garantie dafür, dassServerSocket
über diesen Port eine nachfolgende erstellt werden kann. Das Gleiche gilt fürDatagramSocket
.Für Java 7 können Sie try-with-resource für kompakteren Code verwenden:
quelle
ConnectException: 'connection refused'
, ja sollte es false zurück. Für Zeitüberschreitungen ist nichts gültig, was zurückgegeben werden könnte, da die tatsächliche Antwort nicht bekannt ist. Deshalb ist diese Technik für diesen Zweck nutzlos.Ab Java 7 scheint die Antwort von David Santamaria nicht mehr zuverlässig zu funktionieren. Es sieht jedoch so aus, als könnten Sie die Verbindung weiterhin zuverlässig mit einem Socket testen.
quelle
Wenn Sie sich nicht zu sehr mit der Leistung befassen, können Sie jederzeit versuchen, einen Port mit der ServerSocket- Klasse abzuhören . Wenn es eine Ausnahme auslöst, werden die Chancen verwendet.
BEARBEITEN: Wenn Sie nur versuchen, einen freien Port auszuwählen
new ServerSocket(0)
, finden Sie einen für Sie.quelle
Die folgende Lösung ist von der SocketUtils- Implementierung von Spring-Core (Apache-Lizenz) inspiriert .
Im Vergleich zu anderen Lösungen ist die Verwendung
Socket(...)
ziemlich schnell (Testen von 1000 TCP-Ports in weniger als einer Sekunde):quelle
Die auf Try / Catch-Sockets basierenden Lösungen liefern möglicherweise keine genauen Ergebnisse (die Socket-Adresse lautet "localhost", und in einigen Fällen kann der Port nicht von der Loopback-Schnittstelle "belegt" werden, und zumindest unter Windows ist dieser Test fehlgeschlagen, z der Schutz fälschlicherweise als verfügbar deklariert).
Es gibt eine coole Bibliothek namens SIGAR , der folgende Code kann Sie verbinden:
quelle
Eine Bereinigung der Antwort von David Santamaria:
Dies unterliegt immer noch einer Rennbedingung, auf die user207421 in den Kommentaren zu David Santamarias Antwort hingewiesen hat (etwas könnte den Port greifen, nachdem diese Methode das
ServerSocket
und geschlossen hatDatagramSocket
und zurückkehrt).quelle
In meinem Fall hat es geholfen, eine Verbindung zum Port herzustellen. Wenn der Dienst bereits vorhanden ist, reagiert er.
quelle
In meinem Fall musste ich die DatagramSocket-Klasse verwenden.
Vergessen Sie nicht, zuerst zu importieren
quelle
Ich habe so etwas ausprobiert und es hat bei mir sehr gut funktioniert
quelle