Telnet 協議雖老舊但仍廣泛用於網路設備管理、舊系統整合。Apache Commons Net 提供 TelnetClient 封裝協議細節。本文封裝一個可重用的 TelnetUtil 類別,支援連線、登入、指令執行、編碼設定與資源釋放。
<dependency>
<groupId>commons-net</groupId>
<artifactId>commons-net</artifactId>
<version>3.9.0</version> <!-- 最新版本 -->
</dependency>
public class TelnetUtil {
private String charset = "UTF-8";
private byte[] buffer = new byte[2048];
private TelnetClient client = new TelnetClient();
private BufferedReader reader;
private BufferedWriter writer;
private InputStream in;
private OutputStream out;
// 連線 (預設埠 23)
public void connect(String ip, int port) throws IOException {
client.connect(ip, port);
initStreams();
}
public void connect(String ip) throws IOException { connect(ip, 23); }
private void initStreams() throws UnsupportedEncodingException {
in = client.getInputStream();
out = client.getOutputStream();
reader = new BufferedReader(new InputStreamReader(in, charset));
writer = new BufferedWriter(new OutputStreamWriter(out, charset));
}
// 登入流程 (自動處理 login:/Password: 提示)
public boolean login(String user, String pass) throws IOException {
String line = readUntil("login:");
writer.write(user + "\r\n"); writer.flush();
line = readUntil("Password:");
writer.write(pass + "\r\n"); writer.flush();
line = readUntil("Last login:", "incorrect");
return line.contains("Last login:");
}
// 執行指令並回傳輸出
public String exec(String cmd) throws IOException {
writer.write(cmd + "\r\n"); writer.flush();
return readUntilPrompt(); // 需依目標系統提示符調整
}
// 讀取直到關鍵字出現
private String readUntil(String... keywords) throws IOException {
StringBuilder sb = new StringBuilder();
while (true) {
String line = reader.readLine();
if (line == null) break;
sb.append(line).append("\n");
for (String kw : keywords) if (line.contains(kw)) return sb.toString();
}
return sb.toString();
}
// 關閉資源
public void close() {
try { writer.write("exit\r\n"); writer.flush(); } catch (Exception ignored) {}
closeQuietly(in); closeQuietly(out);
try { client.disconnect(); } catch (Exception ignored) {}
}
private void closeQuietly(Closeable c) { try { if (c != null) c.close(); } catch (Exception ignored) {} }
// 設定編碼 (需在 connect 前呼叫)
public void setCharset(String cs) { this.charset = cs; }
public void setBufferSize(int size) { this.buffer = new byte[size]; }
}
public static void main(String[] args) {
TelnetUtil telnet = new TelnetUtil();
telnet.setCharset("UTF-8"); // 依伺服器編碼調整
try {
telnet.connect("192.168.1.1", 23);
if (telnet.login("admin", "password")) {
System.out.println("登入成功");
String output = telnet.exec("show version");
System.out.println("指令輸出:\n" + output);
} else {
System.err.println("登入失敗");
}
} catch (IOException e) {
e.printStackTrace();
} finally {
telnet.close();
}
}
#, >, $),readUntilPrompt() 需客製化。setCharset() 對應,否則會亂碼。readLine(),高併發場景建議改用非阻塞 I/O 或獨立執行緒讀取。login:/Password: (某些設備為 Username:)。\r 或 \r\n,或指令需進入特定模式 (如 enable、configure terminal)。