Web_telnet 通過JAVA實現網頁上面的命令列遠端工具 以及對於流的理解
前言
這幾天研究了一下如何在web頁面上通過telnet 連線一個遠端的機器,通過命令列進行控制,讓然,B/S架構的專案,如果直接通過
瀏覽器是無法和遠端機器進行通訊的,我們就得藉助後端來幫助實現這樣的一個功能需求,具體的實現邏輯是:
使用者————>控制瀏覽器命令列介面————>傳送命令到後端伺服器————>後端伺服器連線socket————>推送使用者的命令
telnet Server ————>後端伺服器輸入流接受返回字元——————>websocket 推送到前端完成互動
telnet
可能很多人都知道ssh,估計很少會了解到關於telnet的東西,但是又結合起來說,其實兩個都是一種協議,可以遠端操控,
但是telnet 在傳輸過程中存在著不安全的因素,因為傳輸都未經過加密,而都是明文,這就在遠端連線中,很容易就會被抓包,出現問題,
但SSH 就好比是加強版的telnet ,在傳輸過程中的資料進行加密,進而減少了被盜取的風險。並且所有的SSH都是經過壓縮的,在網路上的
傳輸速率也很優秀,這樣多方面優秀的情況下,自然而然的就會代替掉telnet
並不是這樣說telnet 就沒什麼用了,也不是這樣子的,我們通過搭建這樣一個demo 學習的是這樣的搭建過程中去了解建立連線的過程以及互動的過程
同樣的,就算改編成SSH 其實也是這樣的一個過程,學習就是一個不斷探索的過程
開始
後端的話,從Springboot 入手,快速的搭建一個web工程,我們主要用這個web工程來接受前端傳送過來的命令請求。
包括:連線、斷開、傳送命令等等。
最主要的,就是採用commons-net包下面的TelnetClient
<dependency> <groupId>commons-net</groupId> <artifactId>commons-net</artifactId> <version>3.6</version> </dependency>
就好比我們的交換機作為一個Telnet的服務端,而我們的本機就作為一個Telnet的客戶端,客戶端發起請求,服務端相應,與B/S其實一樣的
這裡我就摘一些關鍵的部分來進行講解,其他的請clone 專案進行檢視
建立一個telnet 客戶端
其實建立一個telnet 客戶端是很簡單的,就只需要new一個物件,而後填寫ip地址和埠,埠預設是23,可以不寫,就打開了一個telnet的Connection
telnetClient = new TelnetClient(); telnetClient.connect(ip,port); inputStream = telnetClient.getInputStream(); outputStream = telnetClient.getOutputStream();
從客戶端得到兩個流,一個輸入流,一個輸出流,這裡就會涉及到JAVA關於IO相關的知識,當然網路上一般通行都是採用位元組流
inputStream 輸入流 outputStread 輸出流
對於輸入流和輸出流相對於模糊的小夥伴,這裡給大家加深一下理解,從字面意思上理解
輸入流:就是輸進來的
輸出流:就是丟出去的
其實這樣理解的話,丟失了一個基於的物件。那就是,到底是基於客戶端還是服務端呢,我這裡簡單的畫個圖
就好比你的程式要讀取一個檔案,這個時候就需要用到輸入流,輸入流提供一個read的方法
我得把日誌資訊寫入到日誌檔案裡,這個時候就需要用到輸出流,輸出流提供一個write() 方法
輸出流有一個flush() 強制重新整理的方法 強制清空和寫入
一個好的習慣,流用完之後要進行關閉!!!!!
在當前的環境裡面,輸入流就好比是客戶端給我們返回的資料,而輸出流才是我們推送命令的
輸入命令
切記在命令後加入一個換行符,這就好比我們在telnet 客戶端上面操作的時候,寫完一句就需要敲一個回車,一樣的道理。
通過輸出流的write 方法寫入到輸出流裡面,flush將輸出流清空和強制寫入命令。
public String sendCommand(String send) throws IOException { //加入換行符 send = send + "\n"; if (null == telnetClient) { return "連線已關閉"; } outputStream.write(send.getBytes()); outputStream.flush(); return "傳送成功"; }
讀取服務端的返回
上面已經反覆敘述過了,服務端的返回我們需要採用輸入流進行接收,同樣的,需要從流裡面讀取出我們需要的位元組,並將其轉換為字元
通過webSocket 推送到前臺進行展示
這時候就需要起一個執行緒來操作了,因為你不知道什麼時候回接收到推送的訊息,所以這個執行緒還不能停掉,得設定為後臺執行緒,讓它在開啟連線後一直
在後臺保持活動狀態,這裡就需要了解一下:守護執行緒
守護執行緒 、後臺執行緒
通過給一個執行緒設定setDaemon(true) 的形式標記這個執行緒為守護執行緒,也就是後臺執行緒,執行緒啟動前必須啟動這個執行緒
對於停止這個執行緒的方法嘛 那就是執行中斷,在這個執行緒的邏輯程式碼中判斷是否中斷,中斷則跳出這個執行緒,執行緒執行完畢
這個執行緒也就停掉了唄!
通過new 一個執行緒類,主要看一下這個類的實現方法
outputThread = new InputPrintThread(inputStream); //守護執行緒 outputThread.setDaemon(true); outputThread.start();
通過一個while 迴圈的方式時刻執行是否中斷的方法和 對輸入流進行讀取,因為讀取在讀取不到位元組的時候會發生阻塞,所以這樣是很有必要的
因為在讀取不到的時候,會阻塞這個執行緒,若讀取流在檔案末尾,則會返回-1 我們只需要判斷不是-1繼續讀取就好了
注意:這裡說的是:讀取出一些位元組,並不是所有的位元組,一次返回過來的位元組它可能會讀取多次,所以不能只迴圈一次就判斷這個就完了
@Override public void run() { int num = 0; //位元組緩衝 char[] bytes = new char[1024]; InputStreamReader inputStreamReader = new InputStreamReader(inputStream); try { //這裡會發生阻塞,通過websocket推送進行 while (!interrupted() && (num = inputStreamReader.read(bytes)) != -1) { for (int i = 0; i < num; i++) { char ab = bytes[i]; WebSocketServer.sendInfo(ab + "", SocketIdEnum.TELNET.getValue()); } } } catch (IOException e) { e.printStackTrace(); } }
webSocket 推送
這一部分對於Springboot 來說整合WebSocket 簡直是太簡單了,一個POM依賴以及簡單的幾行配置即可開啟
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-websocket</artifactId> </dependency>
這裡我就不細說了:我的內容也是參考這一篇文章:請參閱
https://blog.csdn.net/moshowgame/article/details/80275084
telnet 客戶端的配置
在windows 裡面開啟telnet 基本步驟:搜尋windows功能
找到並開始這一項即可,即可在命令列裡面通過telnet + ip 進行遠端訪問,
telnet 測試服務端
很多小夥伴在昨晚後,不知如何去測試telnet的連通性以及程式碼的測試,缺少一個測試的環境
手頭又沒有其他閒置的電腦或者是交換機,可以參考手頭建立一個虛擬機器的方式,這樣也行,或者就
採用華為的ENSP 建立一個虛擬的交換機後,通過自己電腦的虛擬網絡卡接入到虛擬交換機,這樣其實也是可以通過telnet
進行訪問的,ENSP的安裝這裡略過,這裡給一個連結:https://share.weiyun.com/5kmSEYr
而後新建一個交換機通過虛擬網絡卡的對映進行連線後,通過本機PING 這臺交換機的IP 若ping通則證明連線正常
若不清楚配置交換機的telnet 可以參閱:https://www.cnblogs.com/pipci/p/8075686.html
劃分vlan 這些基礎我就不細說了,自行參考
測試效果
對與一個寫後臺的人來說:前臺這樣子其實已經很不錯了
哈哈 只能簡單的寫個視窗,然後將後臺推送的內容push到頁面上
因為是一個小的測試demo 有興趣的可以進行改造升級更好的CSS美化
小結
關於研究這個web版本的telnet 其實還是涉及到很多東西,比如又再一次的學習到了流的概念以及
之前從未知道這個輸入流還會存在阻塞的問題 以及如何優雅的關閉流以及flush 強制重新整理寫入等諸多的問題
雖然SSH已經是遠端當中的主流,telnet 也未必沒得用,總結一下總是好的。
參考
交換機telnet配置 https://www.cnblogs.com/pipci/p/8075686.html
springboot 配置websocket https://www.cnblogs.com/pipci/p/8075686.html
程式碼開源
https://gitee.com/mrc1999/web-tel