昨晚搞定 Telnet 連線程式後, 早上到公司立刻改寫以便測試是否能連線某主機, 然後遠端下指令後, 取得系統資訊, 經過剖析處理後放入資料庫以方便營運管理. 改寫的程式參考前篇文章 :
# Java 的 Telnet 實作
此主機連線後會先要求輸入帳號與密碼認證 :
Enter User Name
>asabulu
Enter Password
>********
因此這裡必須持續攔截輸入串流是否出現 "Enter User Name" 以及 ">", 是的話就將帳號寫入輸出串流, 然後再攔截輸入串流是否出現 "Enter Password" 以及 ">", 是的話就將密碼寫入輸出串流, 這樣就可以登入系統, 可以下達指令了, 例如顯示某資料表內容. 此系統在顯示結束時會以 "BOTTOM" 字串結尾, 因此可用來辨認下達一個指令後, 伺服主機回應的資料是否列印完畢, 達成同步的目的.
之前使用 Javascrip 去呼叫 Putty 做 Telnet 連線取得資料的做法, 因為 Javascript 無法取得輸出入串流, 因此無法與主機同步, 下達指令後還要預估資料要花多少時間才會列印完畢, 然後安插適當的 wait 秒數, 才能下達下一個指令, 否則不同資料表的內容就會前後穿插列印, 導致後續剖析程式分析錯誤. 這種不同步的通訊方式現在看起來還真可笑, 但卻成功運作了兩年之久.
import java.io.*;
import java.net.*;
public class test9_1 {
static Socket socket;
static BufferedInputStream bis;
static BufferedReader r;
static PrintWriter w;
public static void main(String[] args) {
try {
String host="aa.bbb.cc.dd"; //Telnet 伺服主機
int port=23;
String usr="asabulu\n"; //帳號
String pwd="blabla\n"; //密碼
if (connect(host,port,usr,pwd)) {System.out.println("connected");}
else {System.out.println("not connected");}
socket.close();
}
catch (Exception e) {e.printStackTrace();}
}
public static boolean connect(String host,String usr,String pwd) {
return connect(host,23,usr,pwd); //預設 port 23
}
public static boolean connect(String host,int port,String usr,String pwd) {
try {
socket=new Socket(host, port);
socket.setKeepAlive(true);
bis=new BufferedInputStream(socket.getInputStream());
w=new PrintWriter(socket.getOutputStream(),true);
if (readUntil("Enter User Name")==null) {return false;}
if (readUntil(">")==null) {return false;}
Thread.sleep(2000);
send(usr);
Thread.sleep(500);
if (readUntil("Enter Password")==null) {return false;}
if (readUntil(">")==null) {return false;}
Thread.sleep(500);
send(pwd, false); //不於本機顯示密碼
Thread.sleep(500);
if (readUntil(">")==null) {return false;}
Thread.sleep(2000);
send("lis table aaa;");
if (readUntil("BOTTOM")==null) {return false;}
Thread.sleep(5000);
return true; // connect OK
}
catch (Exception e) {e.printStackTrace();return false;}
}
public static void send(String command) {
send(command, true); //預設本機顯示應傳送之命令
}
public static void send(String command, boolean echo) { //傳送指令
try {
w.println(command);
w.flush();
if (echo) {System.out.println(command);} //顯示所傳送之指令
}
catch (Exception e) {e.printStackTrace();}
}
public static String readUntil(String pattern) {
try {
char lastChar=pattern.charAt(pattern.length()-1); //紀錄要攔截的最後一個字元
StringBuffer sb=new StringBuffer(); //暫存輸入串流讀入之內容
char ch=(char)bis.read(); //一次讀取一個字元
while(true) { //無限迴圈
System.out.print(ch); //顯示讀入之字元
sb.append(ch); //讀入之字元存入緩衝器
if (ch==lastChar && sb.toString().endsWith(pattern)) {
return sb.toString(); //找到目標字串, 傳回讀取之串流字串 (可用來存檔)
}
ch=(char)bis.read(); /續讀
}
}
catch(Exception e) {e.printStackTrace();}
return null;
}
}
實際測試可成功登入主機並下達顯示資料表之命令. 此處我還沒有處理主機傳回資料的存檔問題, 雖然這是我真正的目的, 但我想把程式改成物件化與多緒執行再來.
沒有留言:
張貼留言