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 で利用可能かどうかをチェックしています。
お役に立てれば。
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;
}
}
パフォーマンスにあまり関心がない場合は、 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)
ことだけであるなら、あなたのためにそれを見つけるでしょう。
Java 7 の時点で、David Santamaria の回答は確実に機能しなくなったようです。ただし、ソケットを確実に使用して接続をテストできるようです。
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);
}
}
}
}
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;
私の場合、ポートへの接続を試みるのに役立ちました。サービスがすでに存在する場合は、応答します。
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;