Java를 사용하여 주어진 시스템에서 포트의 가용성을 프로그래밍 방식으로 어떻게 결정합니까?
즉, 포트 번호가 주어지면 이미 사용 중인지 여부를 결정합니까?.
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도 확인하고 있습니다.
도움이 되었기를 바랍니다.
ServerSocket
어떤 포트를 청취하는 것이라면 그것이해야 할 일이고 ServerSocket
. 생성 한 다음 닫고 반환하면 ServerSocket
해당 포트를 사용하여 후속 항목 을 만들 수 있다는 보장이 없습니다. 동감을위한 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;
}
}
ConnectException: 'connection refused'
, 네 false를 반환해야합니다. 시간 초과의 경우 실제 답변을 알 수 없으므로 반환 할 수있는 것은 유효하지 않습니다. 그렇기 때문에이 기술은이 목적에 쓸모가 없습니다.
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
반환 한 후에 뭔가 포트를 가져올 수 있음 ).
제 경우에는 포트에 연결을 시도하고 연결하는 데 도움이되었습니다. 서비스가 이미 있으면 응답 할 것입니다.
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;
나는 이것과 같은 것을 시도했고 그것은 나에게 정말 잘 작동했습니다.
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");
}