Embora esta pergunta é sobre como saber se uma determinada porta já está em uso, você pode ter desembarcado aqui tentando encontrar uma maneira de obter um número de porta livre, que stackoverflow.com/questions/2675362/... (com link para a minha essência .github.com / 3429822 ) cobre melhor.
precisa saber é o seguinte
Para qual propósito? Se você quiser apenas encontrar um soquete vazio para escutar, especifique zero. Qualquer técnica de exploração é susceptível de problemas-janela de tempo:. A porta pode ser vago quando você digitalizar e ocupada quando você vai a reivindicação em
/**
* 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;}
Eles também estão verificando o DatagramSocket para verificar se a porta está disponível em UDP e TCP.
Uma boa variante disso, se você tiver MINA, é AvailablePortFinder.getNextAvailable (1024), que fornece a próxima porta sem privilégios.
Alain O'Dea
9
Isso não pega tudo no entanto. Fui mordido por um nginx em execução no TCP 8000, enquanto a rotina acima informa 8000 como disponível. Não faço ideia do porquê - suspeito que o nginx faz algumas coisas sorrateiras (isso é no OS X). A solução para mim é fazer o acima e também abrir um novo soquete ("localhost", porta) e retornar false se não houver uma exceção. Pensamentos?
Parcialmente nublado
2
Mesmo problema no Windows, tentando detectar se o servidor SMTP papercut está em execução. Uma solução em que você abre uma conexão a uma porta, em vez de tentar vinculá-la (como sugerido pelo comentário da Partly Clodys e pela resposta de Ivan) parece funcionar mais confiável.
Stian
4
Interessante. A chamada para setReuseAddress () é completamente inútil após o soquete já estar vinculado e também completamente contrária à finalidade do código.
Marquês de Lorne
3
Este código está sujeito a problemas na janela de temporização. Se o objetivo é criar uma ServerSocketescuta para alguma porta, é isso que ela deve fazer e retornar a ServerSocket. Criá-lo e, em seguida, fechá-lo e devolvê-lo não garante que um subseqüente ServerSocketpossa ser criado usando essa porta. O mesmo vale para DatagramSocket.
Marquês de Lorne
41
No Java 7, você pode usar o try-with-resource para obter um código mais compacto:
Isso não testa se a porta está disponível. Ele testa se está no estado LISTEN, se o endereço IP está acessível etc.
Marquês de Lorne
1
Além disso, este teste é bem lento (quase um segundo por porta).
JMax
ele não deve retornar false quando um IOException é capturado?
Baroudi Safwen 6/08/19
@BaroudiSafwen Depende inteiramente de qual é realmente a exceção. Pois ConnectException: 'connection refused', sim, ele deve retornar falso. Para tempos limite, nada que pudesse retornar seria válido, pois a resposta real não é conhecida. É por isso que essa técnica é inútil para esse fim.
Marquês de Lorne
36
Parece que a partir do Java 7, a resposta de David Santamaria não funciona mais de maneira confiável. Parece que você ainda pode usar um soquete de maneira confiável para testar a conexão.
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);}}}}
Quero verificar se um servidor proxy está disponível para fazer chamadas em seu nome.
Dejell 01/01
1
A resposta de @ DavidSantamaria nunca funcionou. Nada a ver com o Java 7.
Marquis of Lorne
35
Se você não está muito preocupado com o desempenho, sempre pode tentar ouvir uma porta usando a classe ServerSocket . Se ele lança uma exceção, as probabilidades estão sendo usadas.
Use finalmente para limpeza (tente {...} pegar {...} finalmente {if (socket! = Null) socket.close ();} #
Hosam Aly
Você também pode definir "portTaken = (socket == null);" no final, em vez de fazê-lo na captura.
Hosam Aly 12/01/2009
1
Não senti que isso se enquadrasse no escopo pretendido da pergunta do autor.
Spencer Ruport
1
Existe uma maneira de fazer isso sem tentar / pegar? Eu não me importaria de usar nenhuma porta disponível para meus propósitos, mas iterar sobre os números de porta e tentar capturar cada uma delas até encontrar uma gratuita é um pouco inútil. Não existe um método 'nativo booleano disponível (int)' em algum lugar, que apenas verifica?
Oren Shalev
27
O novo SeverSocket (0) selecionará automaticamente uma porta livre.
Spencer Ruport
10
A solução a seguir é inspirada na implementação do Spring-core do SocketUtils (licença Apache).
Comparado a outras soluções Socket(...), é bastante rápido (testando 1000 portas TCP em menos de um segundo):
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;}}
As soluções baseadas em soquete try / catch podem não gerar resultados precisos (o endereço do soquete é "localhost" e, em alguns casos, a porta pode ser "ocupada" não pela interface de loopback e, pelo menos no Windows, vi esse teste falhar, ou seja o prot falsamente declarado como disponível).
Há uma biblioteca legal chamada SIGAR , o seguinte código pode conectá-lo:
Recebo: "no sigar-x86-winnt.dll em java.library.path" Infelizmente, é necessário o download de alguma dll adicional que não é realmente viável no ambiente corporativo (não tenho controle sobre o sistema de CI). Tão ruim .... Obrigado de qualquer maneira.
Uthomas 18/04
@uthomas Eu acho que você ainda tem controle sobre o pacote de implantação de aplicativos, se esse for o caso, você sempre pode fornecer DLL / SOs de tempo de execução nativo Sigar perto dos seus JARs e definir o caminho da lib JAVA de forma pragmática aplicativo lançado pela JVM).
Shmil The Cat
2
Uma limpeza da resposta apontada por 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;}}
Isso ainda está sujeita a uma condição de corrida apontado por user207421 nos comentários a resposta de David Santamaria (algo poderia pegar o porto após esse método fecha o ServerSockete DatagramSockete volta).
No meu caso, ajudou a tentar conectar-se à porta - se o serviço já estiver presente, ele responderia.
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);}
Isso funciona para portas UDP. A pergunta parece ser sobre portas TCP.
Marquês de Lorne
-2
Eu tentei algo assim e funcionou muito bem comigo
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");}
Respostas:
Esta é a implementação proveniente do projeto Apache camel :
Eles também estão verificando o DatagramSocket para verificar se a porta está disponível em UDP e TCP.
Espero que isto ajude.
fonte
ServerSocket
escuta para alguma porta, é isso que ela deve fazer e retornar aServerSocket
. Criá-lo e, em seguida, fechá-lo e devolvê-lo não garante que um subseqüenteServerSocket
possa ser criado usando essa porta. O mesmo vale paraDatagramSocket
.No Java 7, você pode usar o try-with-resource para obter um código mais compacto:
fonte
ConnectException: 'connection refused'
, sim, ele deve retornar falso. Para tempos limite, nada que pudesse retornar seria válido, pois a resposta real não é conhecida. É por isso que essa técnica é inútil para esse fim.Parece que a partir do Java 7, a resposta de David Santamaria não funciona mais de maneira confiável. Parece que você ainda pode usar um soquete de maneira confiável para testar a conexão.
fonte
Se você não está muito preocupado com o desempenho, sempre pode tentar ouvir uma porta usando a classe ServerSocket . Se ele lança uma exceção, as probabilidades estão sendo usadas.
EDIT: Se tudo o que você está tentando fazer é selecionar uma porta gratuita,
new ServerSocket(0)
ela encontrará uma para você.fonte
A solução a seguir é inspirada na implementação do Spring-core do SocketUtils (licença Apache).
Comparado a outras soluções
Socket(...)
, é bastante rápido (testando 1000 portas TCP em menos de um segundo):fonte
As soluções baseadas em soquete try / catch podem não gerar resultados precisos (o endereço do soquete é "localhost" e, em alguns casos, a porta pode ser "ocupada" não pela interface de loopback e, pelo menos no Windows, vi esse teste falhar, ou seja o prot falsamente declarado como disponível).
Há uma biblioteca legal chamada SIGAR , o seguinte código pode conectá-lo:
fonte
Uma limpeza da resposta apontada por David Santamaria:
Isso ainda está sujeita a uma condição de corrida apontado por user207421 nos comentários a resposta de David Santamaria (algo poderia pegar o porto após esse método fecha o
ServerSocket
eDatagramSocket
e volta).fonte
No meu caso, ajudou a tentar conectar-se à porta - se o serviço já estiver presente, ele responderia.
fonte
No meu caso, eu tive que usar a classe DatagramSocket.
Não se esqueça de importar primeiro
fonte
Eu tentei algo assim e funcionou muito bem comigo
fonte