ฉันจะตรวจสอบความพร้อมใช้งานของพอร์ตในเครื่องที่กำหนดโดยใช้ Java โดยทางโปรแกรมได้อย่างไร
เช่นระบุหมายเลขพอร์ตตรวจสอบว่ามีการใช้งานอยู่แล้วหรือไม่?
ฉันจะตรวจสอบความพร้อมใช้งานของพอร์ตในเครื่องที่กำหนดโดยใช้ Java โดยทางโปรแกรมได้อย่างไร
เช่นระบุหมายเลขพอร์ตตรวจสอบว่ามีการใช้งานอยู่แล้วหรือไม่?
คำตอบ:
นี่คือการใช้งานที่มาจากโครงการอูฐ Apache :
/**
* 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 หรือไม่
หวังว่านี่จะช่วยได้
ServerSocket
ฟังพอร์ตบางพอร์ตนั่นคือสิ่งที่ควรทำและส่งคืนไฟล์ServerSocket
. การสร้างแล้วปิดและส่งคืนเป็นการรับประกันเป็นศูนย์ว่าServerSocket
สามารถสร้างรายการที่ตามมาได้โดยใช้พอร์ตนั้น Ditto สำหรับ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'
ใช่มันควรส่งคืนเท็จ สำหรับการหมดเวลาไม่มีสิ่งใดที่สามารถคืนค่าได้เนื่องจากไม่ทราบคำตอบที่แท้จริง นั่นเป็นเหตุผลที่เทคนิคนี้ไม่มีประโยชน์สำหรับจุดประสงค์นี้
ดูเหมือนว่าใน Java 7 คำตอบของ David Santamariaไม่ได้ผลอย่างน่าเชื่อถืออีกต่อไป ดูเหมือนว่าคุณยังสามารถใช้ Socket เพื่อทดสอบการเชื่อมต่อได้อย่างน่าเชื่อถือ
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,000 พอร์ต 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 ฉันเคยเห็นการทดสอบนี้ล้มเหลวเช่น มีการประกาศอย่างไม่ถูกต้องว่ามีอยู่)
มีห้องสมุดสุดเท่ชื่อ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;
}
}
สิ่งนี้ยังคงอยู่ภายใต้เงื่อนไขการแข่งขันที่ user207421 ชี้ให้เห็นในความคิดเห็นต่อคำตอบของ David Santamaria (มีบางอย่างที่สามารถคว้าพอร์ตได้หลังจากวิธีนี้ปิดServerSocket
และ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");
}