Java kullanarak belirli bir makinedeki bir bağlantı noktasının kullanılabilirliğini programlı olarak nasıl belirlerim?
yani bir port numarası verildiğinde, halihazırda kullanılıp kullanılmadığını belirleyin.
Java kullanarak belirli bir makinedeki bir bağlantı noktasının kullanılabilirliğini programlı olarak nasıl belirlerim?
yani bir port numarası verildiğinde, halihazırda kullanılıp kullanılmadığını belirleyin.
Yanıtlar:
Bu uygulama , Apache gelen deve projesi:
/**
* 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;
}
Portun UDP ve TCP'de mevcut olup olmadığını kontrol etmek için DatagramSocket'i de kontrol ediyorlar.
Bu yardımcı olur umarım.
ServerSocket
bağlantı noktası için dinleme oluşturmaksa , yapması gereken budur ve ServerSocket
. Oluşturmak ve sonra kapatmak ve geri döndürmek, ServerSocket
o bağlantı noktası kullanılarak bir sonraki oluşturulabileceğine dair sıfır garanti sağlar . Ditto için DatagramSocket
.
Java 7 için, daha derli toplu bir kod için kaynakla dene'yi kullanabilirsiniz:
private static boolean available(int port) {
try (Socket ignored = new Socket("localhost", port)) {
return false;
} catch (IOException ignored) {
return true;
}
}
ConnectException: 'connection refused'
evet yanlış döndürmelidir. Gerçek cevap bilinmediğinden, zaman aşımları için geri dönebileceği hiçbir şey geçerli olmaz. Bu nedenle bu teknik bu amaç için kullanışsızdır.
Görünüşe göre Java 7'den itibaren David Santamaria'nın cevabı artık güvenilir bir şekilde çalışmıyor. Bununla birlikte, bağlantıyı test etmek için bir Soketi hala güvenilir bir şekilde kullanabileceğiniz görülüyor.
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);
}
}
}
}
Performansla çok ilgilenmiyorsanız, ServerSocket sınıfını kullanarak her zaman bir bağlantı noktasında dinlemeyi deneyebilirsiniz . Bir istisna atarsa, muhtemelen kullanılıyor demektir.
public static boolean isAvailable(int portNr) {
boolean portFree;
try (var ignored = new ServerSocket(portNr)) {
portFree = true;
} catch (IOException e) {
portFree = false;
}
return portFree;
}
DÜZENLEME: Tek yapmaya çalıştığınız boş bir bağlantı noktası seçmekse new ServerSocket(0)
, o zaman sizin için bir tane bulacaktır.
Aşağıdaki çözüm, SocketUtils'ten ilham almıştır Spring- (Apache lisansı) uygulamasından .
Kullanan diğer çözümlerle karşılaştırıldığında Socket(...)
oldukça hızlıdır (bir saniyeden daha kısa sürede 1000 TCP bağlantı noktasını test etmek):
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 soket tabanlı çözümler doğru sonuçlar vermeyebilir (soket adresi "localhost" ve bazı durumlarda bağlantı noktası geri döngü arayüzü tarafından "işgal edilmiş" olabilir ve en azından Windows'ta bu testin başarısız olduğunu gördüm. protesto yanlış bir şekilde mevcut olarak ilan edildi).
SIGAR adında harika bir kütüphane var, aşağıdaki kod sizi bağlayabilir :
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;
David Santamaria'nın işaret ettiği cevabın temizliği:
/**
* 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;
}
}
Bu hala, kullanıcı207421 tarafından David Santamaria'nın cevabına yapılan yorumlarda belirtilen bir yarış durumuna tabidir (bu yöntem ServerSocket
ve DatagramSocket
ve geri döndükten sonra bir şey bağlantı noktasını yakalayabilir ).
Benim durumumda, bağlantı noktasına bağlanmayı denemeye yardımcı oldu - hizmet zaten mevcutsa, yanıt verecektir.
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);
}
Benim durumumda DatagramSocket sınıfını kullanmak zorunda kaldım.
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;
}
}
Önce içe aktarmayı unutmayın
import java.net.DatagramSocket;
import java.net.BindException;
import java.net.SocketException;
Bunun gibi bir şey denedim ve bende gerçekten iyi çalıştı
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");
}