利用 JDK 1.5+ ExecutorService 線程池技術,實現高效 TCP 端口掃描器。核心採用固定大小線程池並行嘗試連接目標 IP 端口,避免逐個串行掃描的低效與無限制建立線程的資源耗盡風險。
private void scanLocal() {
String ip = getLocalIP();
String portStart = txPortStart1.getText().trim();
String portEnd = txPortEnd1.getText().trim();
if (portStart.isEmpty() || portEnd.isEmpty()) return;
int startPort, endPort;
try {
startPort = Integer.parseInt(portStart);
endPort = Integer.parseInt(portEnd);
} catch (Exception ex) {
JOptionPane.showMessageDialog(null, "端口輸入有誤");
return;
}
if (!validPort(startPort) || !validPort(endPort)) {
JOptionPane.showMessageDialog(null, "端口應在 1-65535 範圍");
return;
}
scan(ip, startPort, endPort);
monitorScanCompletion(); // 監控掃描完成
}
private String getLocalIP() {
try { return InetAddress.getLocalHost().getHostAddress(); }
catch (Exception e) { JOptionPane.showMessageDialog(null, "獲取 IP 失敗"); return null; }
}
private void scan(String ip, int startPort, int endPort) {
setButtonsEnabled(false);
status.setText("請稍候...");
tableModel.addRow(new Object[]{ip, ""});
ExecutorService exec = Executors.newFixedThreadPool(10); // 固定 10 線程池
for (int port = startPort; port <= endPort; port++) {
exec.execute(new PortScannerTask(ip, port));
}
exec.shutdown(); // 不再接受新任務,等待現有任務完成
}
class PortScannerTask implements Runnable {
private final String ip;
private final int port;
PortScannerTask(String ip, int port) { this.ip = ip; this.port = port; }
public void run() {
try (Socket socket = new Socket()) {
socket.connect(new InetSocketAddress(ip, port), 200); // 200ms 連接超時
// 連接成功 → 端口開放
SwingUtilities.invokeLater(() ->
updateResult(port, "開放"));
} catch (IOException e) {
// 連接失敗 → 端口關閉/過濾,可選記錄
}
}
}
socket.connect(..., 200) 設定連接超時,防止阻塞過久SwingUtilities.invokeLater() 切回 EDTexec.shutdown() 等待所有任務完成,配合監控線程檢測 isTerminated() 恢復 UI 狀態private void monitorScanCompletion() {
new Thread(() -> {
while (!exec.isTerminated()) {
try { Thread.sleep(500); } catch (InterruptedException ignored) {}
}
SwingUtilities.invokeLater(() -> {
setButtonsEnabled(true);
status.setText("掃描完成");
});
}).start();
}
CompletableFuture 替代 Runnable,支援結果聚合與異常處理ExecutorCompletionService 取得最快結果