Хотя этот вопрос касается того, как узнать, используется ли уже данный порт, вы, возможно, приземлились здесь, пытаясь найти способ получить номер бесплатного порта, который stackoverflow.com/questions/2675362/… (со ссылкой на мою суть .github.com / 3429822 ) покрывает лучше.
vorburger
С какой целью? Если вы просто хотите найти свободный сокет для прослушивания, просто укажите ноль. Любая техника сканирования подвержена проблемам с временным окном: порт может быть пустым, когда вы сканируете, и занятым, когда вы заходите, чтобы подать заявку.
/**
* 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;}
Они также проверяют DatagramSocket, чтобы проверить, доступен ли порт в UDP и TCP.
Хороший вариант этого, если у вас есть MINA, - это AvailablePortFinder.getNextAvailable (1024), который дает вам следующий непривилегированный порт.
Alain O'Dea
9
Однако это не улавливает все. Меня укусил запущенный nginx на TCP 8000, в то время как вышеупомянутая процедура сообщает 8000 как доступный. Понятия не имею, почему - я подозреваю, что nginx делает некоторые подлые вещи (это на OS X). Для меня обходной путь - это сделать описанное выше, а также открыть новый Socket ("localhost", порт), а затем вернуть false, если мы не получим исключения. Мысли?
Небольшая
2
Та же проблема в Windows при попытке определить, работает ли SMTP-сервер papercut. Решение, в котором вы открываете соединение с портом, а не пытаетесь привязаться к нему (как это было предложено комментарием Partly Clodys и ответом Ивана), кажется, работает более надежно.
stian
4
Интересный. Вызов setReuseAddress () совершенно бессмысленен после того, как сокет уже привязан, и это также полностью противоречит цели кода.
Marquis of Lorne
3
Этот код подвержен проблемам с временным окном. Если цель состоит в том, чтобы создать ServerSocketпрослушивающий какой-либо порт, это то, что он должен сделать, и вернуть файл ServerSocket. Создание его, а затем его закрытие и возврат дает нулевую гарантию того, что последующий ServerSocketможет быть создан с использованием этого порта. То же самое для DatagramSocket.
Маркиз Лорн
41
Для Java 7 вы можете использовать try-with-resource для более компактного кода:
Это не проверяет, доступен ли порт. Он проверяет, находится ли он в состоянии LISTEN, доступен ли IP-адрес и т. Д.
Marquis of Lorne
1
Кроме того, этот тест довольно медленный (почти секунда на порт).
JMax
Разве он не должен возвращать false при обнаружении исключения IOException?
Baroudi Safwen
@BaroudiSafwen Это полностью зависит от фактического исключения. Ибо ConnectException: 'connection refused'да, он должен вернуть false. Для тайм-аутов ничего, что он мог бы вернуть, не будет действительным, поскольку фактический ответ неизвестен. Поэтому эта техника для этой цели бесполезна.
Marquis of Lorne
36
Похоже, что с Java 7 ответ Дэвида Сантамарии больше не работает надежно. Однако похоже, что вы все еще можете надежно использовать Socket для проверки соединения.
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);}}}}
Я хочу проверить, доступен ли прокси-сервер для звонков от его имени.
Dejell 01
1
Ответ @ DavidSantamaria никогда не работал. Ничего общего с Java 7.
Marquis of Lorne
35
Если вас не слишком заботит производительность, вы всегда можете попробовать прослушивать порт с помощью класса ServerSocket . Если он вызывает исключение, скорее всего, он используется.
Вы также можете установить "portTaken = (socket == null);" в конце вместо того, чтобы делать это в улове.
Хосам Али,
1
Я не чувствовал, что это попадает в рамки заданного автором вопроса.
Спенсер Рупорт,
1
Есть ли способ сделать это без try / catch? Я бы не возражал против использования любого доступного порта для своих целей, но перебирать номера портов и пробовать / перебирать каждый, пока не найду свободный, немного расточительно. Нет ли где-нибудь метода 'native boolean available (int)', который просто проверяет?
Орен Шалев
27
new SeverSocket (0) автоматически выберет свободный порт.
Спенсер Рупорт,
10
Следующее решение основано на реализации SocketUtils Spring-core (лицензия Apache).
По сравнению с другими решениями Socket(...)его использование довольно быстрое (тестирование 1000 портов TCP менее чем за секунду):
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;}}
Решения на основе сокетов try / catch могут не давать точных результатов (адрес сокета - «localhost», и в некоторых случаях порт может быть «занят» не интерфейсом обратной петли, и, по крайней мере, в Windows я видел, что этот тест не прошел, т.е. Прот ложно объявлен доступным).
Существует классная библиотека под названием SIGAR , следующий код может вас зацепить:
Я получаю: «no sigar-x86-winnt.dll in java.library.path» К сожалению, для этого требуется загрузка некоторой дополнительной dll, которая не очень эффективна в корпоративной среде (у меня нет контроля над системой CI). Так плохо .... Все равно спасибо.
uthomas
@uthomas Я думаю, у вас все еще есть контроль над пакетом развертывания приложения, если это так, вы всегда можете предоставить встроенные библиотеки DLL / SO Sigar рядом с вашими JAR и прагматично установить путь к библиотеке JAVA (с помощью простого взлома вы можете повлиять на него даже после приложение было запущено JVM).
Кот Шмиль
2
Очистка ответа, указанного Дэвидом Сантамария:
/**
* 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;}}
Это по-прежнему зависит от состояния гонки, указанного пользователем 207421 в комментариях к ответу Дэвида Сантамария (что-то может захватить порт после того, как этот метод закроет ServerSocketи DatagramSocketи вернется).
В моем случае это помогло попытаться подключиться к порту - если служба уже присутствует, она ответит.
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);}
Это работает для портов UDP. Вопрос, похоже, касается TCP-портов.
Маркиз Лорн,
-2
Я пробовал что-то подобное, и у меня это отлично сработало
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");}
Ответы:
Это реализация из проекта Apache camel :
Они также проверяют DatagramSocket, чтобы проверить, доступен ли порт в UDP и TCP.
Надеюсь это поможет.
источник
ServerSocket
прослушивающий какой-либо порт, это то, что он должен сделать, и вернуть файлServerSocket
. Создание его, а затем его закрытие и возврат дает нулевую гарантию того, что последующийServerSocket
может быть создан с использованием этого порта. То же самое дляDatagramSocket
.Для Java 7 вы можете использовать try-with-resource для более компактного кода:
источник
ConnectException: 'connection refused'
да, он должен вернуть false. Для тайм-аутов ничего, что он мог бы вернуть, не будет действительным, поскольку фактический ответ неизвестен. Поэтому эта техника для этой цели бесполезна.Похоже, что с Java 7 ответ Дэвида Сантамарии больше не работает надежно. Однако похоже, что вы все еще можете надежно использовать Socket для проверки соединения.
источник
Если вас не слишком заботит производительность, вы всегда можете попробовать прослушивать порт с помощью класса ServerSocket . Если он вызывает исключение, скорее всего, он используется.
РЕДАКТИРОВАТЬ: Если все, что вы пытаетесь сделать, это выбрать свободный порт,
new ServerSocket(0)
вы найдете его для вас.источник
Следующее решение основано на реализации SocketUtils Spring-core (лицензия Apache).
По сравнению с другими решениями
Socket(...)
его использование довольно быстрое (тестирование 1000 портов TCP менее чем за секунду):источник
Решения на основе сокетов try / catch могут не давать точных результатов (адрес сокета - «localhost», и в некоторых случаях порт может быть «занят» не интерфейсом обратной петли, и, по крайней мере, в Windows я видел, что этот тест не прошел, т.е. Прот ложно объявлен доступным).
Существует классная библиотека под названием SIGAR , следующий код может вас зацепить:
источник
Очистка ответа, указанного Дэвидом Сантамария:
Это по-прежнему зависит от состояния гонки, указанного пользователем 207421 в комментариях к ответу Дэвида Сантамария (что-то может захватить порт после того, как этот метод закроет
ServerSocket
иDatagramSocket
и вернется).источник
В моем случае это помогло попытаться подключиться к порту - если служба уже присутствует, она ответит.
источник
В моем случае мне пришлось использовать класс DatagramSocket.
Не забудьте сначала импортировать
источник
Я пробовал что-то подобное, и у меня это отлично сработало
источник