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;
}
포트가 UDP 및 TCP에서 사용 가능한지 확인하기 위해 DatagramSocket도 확인하고 있습니다.
도움이 되었기를 바랍니다.
답변
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;
}
}
답변
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);
}
}
}
}
답변
성능에 너무 관심이 없다면 항상 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(...)
이를 사용 하는 다른 솔루션에 비해 매우 빠릅니다 (1 초 이내에 1000 개의 TCP 포트 테스트).
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에서는이 테스트가 실패하는 것을 보았습니다. 사용 가능한 것으로 잘못 선언 된 prot).
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;
답변
David Santamaria가 지적한 답변 정리 :
/**
* 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;
}
}
이것은 여전히 David Santamaria의 답변에 대한 의견에서 user207421이 지적한 경쟁 조건의 영향을받습니다 (이 메서드가 ServerSocket
and를 닫고 DatagramSocket
반환 한 후에 뭔가 포트를 가져올 수 있음 ).