這幾天研究了一下如何在web頁面上經過telnet 鏈接一個遠程的機器,經過命令行進行控制,讓然,B/S架構的項目,若是直接經過html
瀏覽器是沒法和遠程機器進行通訊的,咱們就得藉助後端來幫助實現這樣的一個功能需求,具體的實現邏輯是:前端
用戶————>控制瀏覽器命令行界面————>發送命令到後端服務器————>後端服務器鏈接socket————>推送用戶的命令git
telnet Server ————>後端服務器輸入流接受返回字符——————>websocket 推送到前端完成交互web
可能不少人都知道ssh,估計不多會了解到關於telnet的東西,可是又結合起來講,其實兩個都是一種協議,能夠遠程操控,spring
可是telnet 在傳輸過程當中存在着不安全的因素,由於傳輸都未通過加密,而都是明文,這就在遠程鏈接中,很容易就會被抓包,出現問題,windows
但SSH 就比如是增強版的telnet ,在傳輸過程當中的數據進行加密,進而減小了被盜取的風險。而且全部的SSH都是通過壓縮的,在網絡上的後端
傳輸速率也很優秀,這樣多方面優秀的狀況下,天然而然的就會代替掉telnet 瀏覽器
並非這樣說telnet 就沒什麼用了,也不是這樣子的,咱們經過搭建這樣一個demo 學習的是這樣的搭建過程當中去了解創建鏈接的過程以及交互的過程安全
一樣的,就算改編成SSH 其實也是這樣的一個過程,學習就是一個不斷探索的過程springboot
後端的話,從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 客戶端是很簡單的,就只須要new一個對象,然後填寫ip地址和端口,端口默認是23,能夠不寫,就打開了一個telnet的Connection
telnetClient = new TelnetClient(); telnetClient.connect(ip,port); inputStream = telnetClient.getInputStream(); outputStream = telnetClient.getOutputStream();
從客戶端獲得兩個流,一個輸入流,一個輸出流,這裏就會涉及到JAVA關於IO相關的知識,固然網絡上通常通行都是採用字節流
對於輸入流和輸出流相對於模糊的小夥伴,這裏給你們加深一下理解,從字面意思上理解
輸入流:就是輸進來的
輸出流:就是丟出去的
其實這樣理解的話,丟失了一個基於的對象。那就是,究竟是基於客戶端仍是服務端呢,我這裏簡單的畫個圖
就比如你的程序要讀取一個文件,這個時候就須要用到輸入流,輸入流提供一個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(); } }
這一部分對於Springboot 來講整合WebSocket 簡直是太簡單了,一個POM依賴以及簡單的幾行配置便可開啓
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-websocket</artifactId> </dependency>
這裏我就不細說了:個人內容也是參考這一篇文章:請參閱
http://www.javashuo.com/article/p-kvipcjjl-z.html
在windows 裏面開啓telnet 基本步驟:搜索windows功能
找到並開始這一項便可,便可在命令行裏面經過telnet + ip 進行遠程訪問,
不少小夥伴在昨晚後,不知如何去測試telnet的連通性以及代碼的測試,缺乏一個測試的環境
手頭又沒有其餘閒置的電腦或者是交換機,能夠參考手頭創建一個虛擬機的方式,這樣也行,或者就
採用華爲的ENSP 建立一個虛擬的交換機後,經過本身電腦的虛擬網卡接入到虛擬交換機,這樣其實也是能夠經過telnet
進行訪問的,ENSP的安裝這裏略過,這裏給一個連接:https://share.weiyun.com/5kmSEYr
然後新建一個交換機經過虛擬網卡的映射進行鏈接後,經過本機PING 這臺交換機的IP 若ping通則證實鏈接正常
若不清楚配置交換機的telnet 能夠參閱:http://www.javashuo.com/article/p-gjkjhnnz-ek.html
劃分vlan 這些基礎我就不細說了,自行參考
對與一個寫後臺的人來講:前臺這樣子其實已經很不錯了
哈哈 只能簡單的寫個窗口,而後將後臺推送的內容push到頁面上
由於是一個小的測試demo 有興趣的能夠進行改造升級更好的CSS美化
關於研究這個web版本的telnet 其實仍是涉及到不少東西,好比又再一次的學習到了流的概念以及
以前從未知道這個輸入流還會存在阻塞的問題 以及如何優雅的關閉流以及flush 強制刷新寫入等諸多的問題
雖然SSH已是遠程當中的主流,telnet 也未必沒得用,總結一下老是好的。
交換機telnet配置 http://www.javashuo.com/article/p-gjkjhnnz-ek.html
springboot 配置websocket http://www.javashuo.com/article/p-gjkjhnnz-ek.html