先看看telnet 和ssh的定義:
Telnet協議是TCP/IP協議中的一員,是Internet遠程登陸服務的標準協議和主要方式。它為使用者提供了在本機電腦上完成遠程主機工作的能力。在終端使用者的電腦上使用telnet程式,用它串連到伺服器。終端使用者可以在telnet程式中輸入命令,這些命令會在伺服器上運行,就像直接在伺服器的控制台上輸入一樣。可以在本地就能控制伺服器。要開始一個telnet會話,必須輸入使用者名稱和密碼來登入伺服器。Telnet是常用的遠端控制Web伺服器的方法。
SSH是一個用來替代TELNET、FTP以及R命令的工具包,主要是想解決口令在網上明文傳輸的問題。為了系統安全和使用者自身的權益,推廣SSH是必要的。 SSH是英文Secure Shell的簡寫形式。通過使用SSH,你可以把所有傳輸的資料進行加密,這樣"中間人"這種攻擊方式就不可能實現了,而且也能夠防止DNS欺騙和IP欺騙。
實際上,telnet和ssh的功能基本相同,都是實現遠程登陸的網路通訊協定。
和其他多數協議一樣, java 中telnet ssh的實現也要經過三部曲:建立串連、使用串連 和釋放串連 。ssh是用以替換telnet 的一種協議,在java 編程中 ,ssh和telnet 的不同僅僅表現在建立串連和釋放串連中。
使用串連的過程,其實就是發送命令和遠程伺服器互動的過程,原理也很簡單:每向伺服器發送一條命令,就等待伺服器執行此命令後返回的字元流,暫且把它叫做一次互動。我們以在規定時間內接收這些字元流,如果這些字元流中出現了“命令提示字元”,說明伺服器處於等待狀態,我們就認為此次互動完成,否則,此次互動失敗,出現異常。
linux伺服器上的命令提示字元不多,登陸命令提示字元就更有限了,一般就包括 使用者名稱提示符、密碼提示符 和登陸成功提示符(也叫命令提示字元)這三類,不同linux的使用者命令提示字元、密碼提示符也會稍有不同。
下面簡單寫一個程式做telnet的測試,此程式僅作測試,所以很多寫法並不規範。
(1)所需包:commons-net-2.2.jar
(2)代碼如下:
package telnet;<br />import java.io.IOException;<br />import java.io.InputStream;<br />import java.io.OutputStream;<br />import java.net.SocketException;<br />import java.util.regex.Pattern;<br />import org.apache.commons.net.telnet.TelnetClient;<br />public class Telnet {<br />private TelnetClient telnetClient;<br />private InputStream inputStream;<br />private OutputStream outputStream;<br />private long timeout=30000;//預設逾時為30秒<br />/**<br /> * 建立telnet串連<br /> * @param hostIp 伺服器Ip<br /> * @param port 連接埠號碼 telnet 預設連接埠號碼為23<br /> * @param userName 登陸帳號<br /> * @param password 登陸密碼<br /> * @throws IOException<br /> * @throws SocketException<br /> */<br />public void connect(String hostIp,int port,String userName,String password) throws SocketException, IOException{<br />telnetClient=new TelnetClient();<br />telnetClient.connect(hostIp, port);<br />inputStream=telnetClient.getInputStream(); //接收伺服器訊息的輸入資料流<br />outputStream=telnetClient.getOutputStream(); //發送訊息到伺服器的輸出資料流<br />//串連完畢,伺服器就等待客戶發送 使用者名稱,然後是密碼<br />if(sendLoginInfo(userName,".*PASSWORD:")){//假如發送完使用者名稱後得到的提示符是密碼提示符<br />sendLoginInfo(password, "//]//$"); //假如發送密碼資訊後得到的提示符是命令提示字元<br />}<br />}<br />private boolean sendLoginInfo(String info,String regext){<br />Pattern pattern=Pattern.compile(regext);<br />try {<br />outputStream.write((info+"/n").getBytes());<br />outputStream.flush();<br />int i=-1;<br />StringBuilder sb=new StringBuilder();<br />long startTime=System.currentTimeMillis();<br />while(System.currentTimeMillis()-startTime<timeout){<br />while( (i=(char) inputStream.read())>-1){<br />if(i==-1){<br />throw new IllegalArgumentException("接收不到訊息");<br />}<br />char ch=(char)i;<br />if(ch=='/n'||ch=='/r'){ //命令提示字元是最後在一行的<br />sb.delete(0, sb.length());<br />continue;<br />}<br />sb.append((char)ch);</p><p>if(pattern.matcher(sb.toString()).find()){<br />return true;<br />}<br />}<br />}<br />throw new IllegalArgumentException("逾時收不到提示符");<br />} catch (IOException e) {<br />close();<br />return false;<br />}<br />}</p><p>public String send(String cmd){<br />if(null==telnetClient||null==inputStream||null==outputStream){<br />throw new IllegalArgumentException("請先 建立串連 或建立串連失敗");<br />}<br />Pattern pattern=Pattern.compile("//]//$");//假如命令提示字元為 /$<br />StringBuilder text=new StringBuilder();<br />try {<br />outputStream.write((cmd+"/n").getBytes());<br />outputStream.flush();<br />StringBuilder sb=new StringBuilder();<br />long startTime=System.currentTimeMillis();<br />int i=-1;<br />while(System.currentTimeMillis()-startTime<timeout){<br />while( (i=inputStream.read())>-1){<br />if(i==-1){<br />throw new IllegalArgumentException("接收不到訊息");<br />}<br />char ch=(char)i;<br />text.append(ch);<br />if(ch=='/n'||ch=='/r'){<br />sb.delete(0, sb.length());<br />continue;<br />}<br />sb.append(ch);<br />if(pattern.matcher(sb.toString()).find()){//返回字元流中找到了命令提示字元<br />return text.toString();<br />}<br />}<br />}<br />throw new IllegalArgumentException("逾時收不到提示符");<br />} catch (IOException e) {<br />close();<br />return null;<br />}<br />}<br />public void close(){<br />if(null!=null){<br />try {<br />telnetClient.disconnect();<br />} catch (IOException e) {<br />e.printStackTrace();<br />}<br />}<br />}<br />public static void main(String[] args) throws SocketException, IOException {<br />Telnet telnet=new Telnet();<br />telnet.connect("ip", 23, "username", "passowrd");<br />System.out.println(telnet.send("ls"));<br />telnet.close();<br />}<br />}<br />
ssh 的實現和和 telnet 大同小異,差別在於建立串連和釋放串連:
(1)需要包:jsch-0.1.42.jar
(2) 關鍵代碼如下:
/**<br /> * 建立串連<br /> * @param hostIp 伺服器Ip<br /> * @param port ssh連接埠號碼 預設為 22<br /> * @param userName<br /> * @param password<br /> */<br />public void connect(String hostIp,int port,String userName,String password){<br />try {<br />session=jsch.getSession(userName,hostIp,port );<br />session.setPassword(password);<br />session.setUserInfo(defaultUserInfo);<br />session.connect();<br />channel=session.openChannel("shell");<br />inputStream=channel.getInputStream();<br />outputStream=channel.getOutputStream();<br />} catch (JSchException e) {<br />// TODO Auto-generated catch block<br />e.printStackTrace();<br />}catch (IOException e) {<br />// TODO Auto-generated catch block<br />e.printStackTrace();<br />}<br />}<br /> //關閉串連<br />public void close(){<br /> if(null!=channel){<br /> channel.disconnect();<br /> }<br /> if(null!=session){<br /> session.disconnect();<br /> }<br />}
其中 defaultUserInfo 是實現了UserInfo的一個類對象:
UserInfo defaultUserInfo = new UserInfo() {<br />public String getPassphrase() {<br />return null;<br />}<br />public String getPassword() {<br />return null;<br />}<br />public boolean promptPassword(String arg0) {<br />return false;<br />}<br />public boolean promptPassphrase(String arg0) {<br />return false;<br />}<br />public boolean promptYesNo(String arg0) {<br />return true;<br />}<br />public void showMessage(String arg0) {<br />}<br />}
介紹完畢,歡迎提出寶貴意見!