Jak programowo określić dostępność portu na danej maszynie przy użyciu języka Java?
tzn. mając numer portu, określ, czy jest już używany, czy nie ?.
Jak programowo określić dostępność portu na danej maszynie przy użyciu języka Java?
tzn. mając numer portu, określ, czy jest już używany, czy nie ?.
Odpowiedzi:
Oto implementacja pochodząca z projektu wielbłąda Apache :
/**
* 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;
}
Sprawdzają również DatagramSocket, aby sprawdzić, czy port jest dostępny w UDP i TCP.
Mam nadzieję że to pomoże.
ServerSocket
podsł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 ServerSocket
można utworzyć przy użyciu tego portu. To samo dotyczy DatagramSocket
.
W przypadku Java 7 możesz użyć try-with-resource, aby uzyskać bardziej zwarty kod:
private static boolean available(int port) {
try (Socket ignored = new Socket("localhost", port)) {
return false;
} catch (IOException ignored) {
return true;
}
}
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.
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);
}
}
}
}
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.
public static boolean isAvailable(int portNr) {
boolean portFree;
try (var ignored = new ServerSocket(portNr)) {
portFree = true;
} catch (IOException e) {
portFree = false;
}
return portFree;
}
EDYCJA: Jeśli wszystko, co próbujesz zrobić, to wybrać wolny port new ServerSocket(0)
, znajdziesz go dla siebie.
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ę):
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;
}
}
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ć:
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;
Uporządkowanie odpowiedzi wskazanej przez Davida Santamarię:
/**
* 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;
}
}
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
i DatagramSocket
i 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 = 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);
}
W moim przypadku musiałem użyć klasy 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;
}
}
Nie zapomnij najpierw zaimportować
import java.net.DatagramSocket;
import java.net.BindException;
import java.net.SocketException;
Próbowałem czegoś takiego i działało naprawdę dobrze
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");
}