Chociaż to pytanie dotyczy tego, jak sprawdzić, czy dany port jest już używany, być może wylądowałeś tutaj, próbując znaleźć sposób na uzyskanie wolnego numeru portu, który stackoverflow.com/questions/2675362/ ... (z linkiem do mojego sedna .github.com / 3429822 ) zakrywa lepiej.
vorburger
W jakim celu? Jeśli chcesz tylko znaleźć wolne gniazdo do nasłuchiwania, po prostu podaj zero. Każda technika skanowania może powodować problemy z oknem czasowym: port może być pusty podczas skanowania i zajęty, gdy idziesz zgłosić się do niego.
/**
* 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;}
Sprawdzają również DatagramSocket, aby sprawdzić, czy port jest dostępny w UDP i TCP.
Fajnym wariantem tego, jeśli masz MINA, jest AvailablePortFinder.getNextAvailable (1024), który pobiera następny nieuprzywilejowany port.
Alain O'Dea
9
To jednak nie wszystko. Zostałem ugryziony przez działający nginx na TCP 8000, podczas gdy powyższa procedura zgłasza 8000 jako dostępne. Nie mam pojęcia, dlaczego - podejrzewam, że nginx robi podstępne rzeczy (to jest na OS X). Obejściem dla mnie jest wykonanie powyższego, a także otwarcie nowego Socket („localhost”, port), a następnie zwrócenie false, jeśli nie otrzymamy wyjątku. Myśli?
Częściowe zachmurzenie
2
Ten sam problem w systemie Windows próbuje wykryć, czy serwer SMTP papercut jest uruchomiony. Rozwiązanie, w którym otwierasz połączenie z portem, zamiast próbować się z nim połączyć (jak sugeruje komentarz Partly Clodys i odpowiedź Ivana) wydaje się działać bardziej niezawodnie.
stian
4
Ciekawy. Wywołanie setReuseAddress () jest całkowicie bezcelowe po tym, jak gniazdo jest już związane, a także jest całkowicie sprzeczne z celem kodu.
Markiz Lorne
3
Ten kod podlega problemom z oknami czasowymi. Jeśli celem jest stworzenie ServerSocketpodsłuchiwania jakiegoś portu, to powinno to zrobić i zwrócić plik ServerSocket. Utworzenie go, a następnie zamknięcie i zwrócenie nie daje żadnej gwarancji, że kolejny ServerSocketmożna utworzyć przy użyciu tego portu. To samo dotyczy DatagramSocket.
Markiz Lorne
41
W przypadku Java 7 możesz użyć try-with-resource, aby uzyskać bardziej zwarty kod:
To nie sprawdza, czy port jest dostępny. Sprawdza, czy jest w stanie LISTEN, czy adres IP jest osiągalny itp.
Marquis of Lorne
1
Dodatkowo ten test jest dość powolny (prawie sekunda na port).
JMax
czy nie powinien zwracać false, gdy zostanie przechwycony IOException?
Baroudi Safwen
@BaroudiSafwen To zależy całkowicie od tego, jaki faktycznie jest wyjątek. Bo ConnectException: 'connection refused'tak, to powinno zwrócić fałsz. W przypadku przekroczenia limitów czasu nic, co mogłoby zwrócić, nie byłoby ważne, ponieważ rzeczywista odpowiedź nie jest znana. Dlatego ta technika jest bezużyteczna do tego celu.
Markiz Lorne
36
Wydaje się, że od wersji Java 7 odpowiedź Davida Santamaria nie działa już niezawodnie. Wygląda jednak na to, że nadal możesz niezawodnie używać Socket do testowania połączenia.
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);}}}}
Chcę sprawdzić, czy dostępny jest serwer proxy, aby dzwonić w jego imieniu.
Dejell
1
Odpowiedź @ DavidSantamaria nigdy nie zadziałała. Nie ma nic wspólnego z Javą 7.
Markiz Lorne
35
Jeśli nie przejmujesz się zbytnio wydajnością, zawsze możesz spróbować nasłuchiwać na porcie przy użyciu klasy ServerSocket . Jeśli zgłosi wyjątek, szanse na to, że są używane.
Użyj w końcu do czyszczenia (spróbuj {...} catch {...} w końcu {if (gniazdo! = Null) socket.close ();}
Hosam Aly,
Możesz także ustawić "portTaken = (socket == null);" na końcu zamiast robić to w haczyku.
Hosam Aly,
1
Nie czułem, że mieści się to w zamierzonym zakresie pytania autora.
Spencer Ruport
1
Czy można to zrobić bez try / catch? Nie miałbym nic przeciwko używaniu dowolnego dostępnego portu do moich celów, ale iterowanie po numerach portów i próbowanie / przechwytywanie każdego z nich, dopóki nie znajdę wolnego, jest trochę marnotrawstwem. Czy nie ma gdzieś metody „natywnej dostępnej wartości logicznej (int)”, która po prostu sprawdza?
Oren Shalev
27
new SeverSocket (0) automatycznie wybierze wolny port.
Spencer Ruport
10
Poniższe rozwiązanie jest inspirowane implementacją Spring-core przez SocketUtils (licencja Apache).
W porównaniu do innych rozwiązań wykorzystujących Socket(...)go jest dość szybko (testowanie 1000 portów TCP w mniej niż sekundę):
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;}}
Rozwiązania oparte na gnieździe try / catch mogą nie dawać dokładnych wyników (adres gniazda to „localhost”, aw niektórych przypadkach port może być „zajęty” nie przez interfejs pętli zwrotnej, a przynajmniej w systemie Windows ten test nie powiódł się, tj. protokół fałszywie zadeklarowany jako dostępny).
Istnieje fajna biblioteka o nazwie SIGAR , poniższy kod może Cię podłączyć:
Otrzymuję: „brak sigar-x86-winnt.dll w java.library.path” Niestety wymaga to pobrania dodatkowej biblioteki DLL, która nie jest tak naprawdę możliwa w środowisku korporacyjnym (nie mam kontroli nad systemem CI). Tak źle ... W każdym razie dzięki.
uthomas
@uthomas Wydaje mi się, że nadal masz kontrolę nad pakietem wdrożeniowym aplikacji, jeśli tak jest, zawsze możesz zapewnić natywne biblioteki DLL / SO Sigar w pobliżu plików JAR i ustawić ścieżkę biblioteki JAVA pragmatycznie (za pomocą prostego hacka możesz na to wpłynąć nawet po app została uruchomiona przez JVM).
Shmil The Cat
2
Uporządkowanie odpowiedzi wskazanej przez Davida Santamarię:
/**
* 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;}}
To jest nadal przedmiotem wyścigu wskazane przez user207421 w komentarzach do Dawida Santamaria odpowiedzi (coś może chwycić portu po to metoda zamyka ServerSocketi DatagramSocketi wraca).
W moim przypadku pomogło to przy próbie połączenia się z portem - jeśli usługa jest już obecna, to odpowiadał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);}
Działa to w przypadku portów UDP. Wydaje się, że pytanie dotyczy portów TCP.
Markiz Lorne
-2
Próbowałem czegoś takiego i działało naprawdę dobrze
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");}
Odpowiedzi:
Oto implementacja pochodząca z projektu wielbłąda Apache :
Sprawdzają również DatagramSocket, aby sprawdzić, czy port jest dostępny w UDP i TCP.
Mam nadzieję że to pomoże.
źródło
ServerSocket
podsłuchiwania jakiegoś portu, to powinno to zrobić i zwrócić plikServerSocket
. Utworzenie go, a następnie zamknięcie i zwrócenie nie daje żadnej gwarancji, że kolejnyServerSocket
można utworzyć przy użyciu tego portu. To samo dotyczyDatagramSocket
.W przypadku Java 7 możesz użyć try-with-resource, aby uzyskać bardziej zwarty kod:
źródło
ConnectException: 'connection refused'
tak, to powinno zwrócić fałsz. W przypadku przekroczenia limitów czasu nic, co mogłoby zwrócić, nie byłoby ważne, ponieważ rzeczywista odpowiedź nie jest znana. Dlatego ta technika jest bezużyteczna do tego celu.Wydaje się, że od wersji Java 7 odpowiedź Davida Santamaria nie działa już niezawodnie. Wygląda jednak na to, że nadal możesz niezawodnie używać Socket do testowania połączenia.
źródło
Jeśli nie przejmujesz się zbytnio wydajnością, zawsze możesz spróbować nasłuchiwać na porcie przy użyciu klasy ServerSocket . Jeśli zgłosi wyjątek, szanse na to, że są używane.
EDYCJA: Jeśli wszystko, co próbujesz zrobić, to wybrać wolny port
new ServerSocket(0)
, znajdziesz go dla siebie.źródło
Poniższe rozwiązanie jest inspirowane implementacją Spring-core przez SocketUtils (licencja Apache).
W porównaniu do innych rozwiązań wykorzystujących
Socket(...)
go jest dość szybko (testowanie 1000 portów TCP w mniej niż sekundę):źródło
Rozwiązania oparte na gnieździe try / catch mogą nie dawać dokładnych wyników (adres gniazda to „localhost”, aw niektórych przypadkach port może być „zajęty” nie przez interfejs pętli zwrotnej, a przynajmniej w systemie Windows ten test nie powiódł się, tj. protokół fałszywie zadeklarowany jako dostępny).
Istnieje fajna biblioteka o nazwie SIGAR , poniższy kod może Cię podłączyć:
źródło
Uporządkowanie odpowiedzi wskazanej przez Davida Santamarię:
To jest nadal przedmiotem wyścigu wskazane przez user207421 w komentarzach do Dawida Santamaria odpowiedzi (coś może chwycić portu po to metoda zamyka
ServerSocket
iDatagramSocket
i wraca).źródło
W moim przypadku pomogło to przy próbie połączenia się z portem - jeśli usługa jest już obecna, to odpowiadała.
źródło
W moim przypadku musiałem użyć klasy DatagramSocket.
Nie zapomnij najpierw zaimportować
źródło
Próbowałem czegoś takiego i działało naprawdę dobrze
źródło