Как программно определить доступность порта на данном компьютере с помощью Java?
т.е. учитывая номер порта, определить, используется ли он уже или нет ?.
Как программно определить доступность порта на данном компьютере с помощью Java?
т.е. учитывая номер порта, определить, используется ли он уже или нет ?.
Это реализация из проекта 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;
}
Они также проверяют DatagramSocket, чтобы проверить, доступен ли порт в UDP и TCP.
Надеюсь это поможет.
ServerSocket
, слушающий какой-либо порт, это то, что он должен сделать, и вернуть ServerSocket
. Создание его, а затем его закрытие и возврат дает нулевую гарантию того, что последующий ServerSocket
может быть создан с использованием этого порта. То же для DatagramSocket
.
- person user207421; 01.12.2015
Для Java 7 вы можете использовать try-with-resource для более компактного кода:
private static boolean available(int port) {
try (Socket ignored = new Socket("localhost", port)) {
return false;
} catch (IOException ignored) {
return true;
}
}
ConnectException: 'connection refused'
да, он должен вернуть false. Для тайм-аутов ничего, что он мог бы вернуть, не будет действительным, поскольку фактический ответ неизвестен. Поэтому этот прием для этой цели бесполезен.
- person user207421; 25.11.2019
Похоже, что с Java 7 ответ Дэвида Сантамария больше не работает надежно. Однако похоже, что вы все еще можете надежно использовать Socket для проверки соединения.
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);
}
}
}
}
Если вас не слишком заботит производительность, вы всегда можете попробовать прослушивать порт, используя ServerSocket. Если он вызывает исключение, скорее всего, он используется.
public static boolean isAvailable(int portNr) {
boolean portFree;
try (var ignored = new ServerSocket(portNr)) {
portFree = true;
} catch (IOException e) {
portFree = false;
}
return portFree;
}
РЕДАКТИРОВАТЬ: Если все, что вы пытаетесь сделать, это выбрать свободный порт, new ServerSocket(0)
найдет его для вас.
Следующее решение основано на SocketUtils реализация Spring-core (лицензия Apache).
По сравнению с другими решениями, использующими Socket(...)
, это довольно быстро (тестирование 1000 портов TCP менее чем за секунду).
Конечно, он может обнаруживать только службы, которые открывают порт на всех интерфейсах или явно запускаются на localhost.
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;
}
}
Решения на основе сокетов try / catch могут не дать точных результатов (адрес сокета - «localhost», и в некоторых случаях порт может быть «занят» не интерфейсом обратной петли, и, по крайней мере, в Windows, я видел, что этот тест терпит неудачу, т.е. Прот ложно объявлен доступным).
Существует классная библиотека с именем SIGAR, следующий код может вас зацепить:
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;
Очистка ответа, указанного Дэвидом Сантамария:
/**
* 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;
}
}
Это все еще зависит от состояния гонки, указанного пользователем 207421 в комментариях к ответу Дэвида Сантамария (что-то может захватить порт после того, как этот метод закроет ServerSocket
и DatagramSocket
и вернется).
В моем случае это помогло попытаться подключиться к порту - если служба уже присутствует, она ответит.
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);
}
В моем случае мне пришлось использовать класс 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;
}
}
Не забудьте сначала импортировать
import java.net.DatagramSocket;
import java.net.BindException;
import java.net.SocketException;
Я пробовал что-то подобное, и у меня это отлично сработало
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");
}