0 - 有沒有覺得Linux標準終端介面輸入輸出枯燥無味?
1 - 什麼?vmstat命令的輸出資料不直觀?有沒有想過能夠視覺化該命令的輸出?
2 - 嘗試過用瀏覽器操作Windows中的cmd嗎?
websocketj可以解決以上所有問題,讓你隨時隨地通過瀏覽器訪問任何平臺上的應用程式。
- websocketj是什麼?
- 如何使用websocketj?
- websocketj是如何工作的?
- 在瀏覽器中遠端操作Windows中的cmd
- 在瀏覽器中視覺化Linux中vmstat命令的輸出
- 待完善功能
- 站在巨人肩上
- 如何編譯原始碼
看名字就知道它跟WebSocket有關,簡言之,websocketj能夠將服務端程式的標準輸入輸出(STDIN和STDOUT)重定向到遠端支援WebSocket協議的瀏覽器中。
程式的標準輸出會被當作message傳送到遠端的瀏覽器,來自遠端瀏覽器中的任何資料都會被當作程式的標準輸入。不管你的服務端程式使用什麼語言編寫,只要你的程式支援STDIN和STDOUT,那麼websocketj就可以很好地工作。Java、python、C、C#、Ruby、Swift、Go反正whatever else!
websocketj除了是一個WebSocket伺服器,可以接收websocket client連線之外,還是一個靜態web伺服器,可以處理一些常見的靜態資源請求,比如html、js、css以及圖片之類的。websocketj由Java編寫實現,實現程式碼結構簡單,不依賴其他元件,更不需要tomacat、nginx之類的東西,自己完全獨立執行。Strong!
說了這麼多,那麼該如何使用websocketj呢?使用起來也相當簡單,下面是使用websocketj的步驟:
- Step1:開發你的服務端程式,不受語言限制,但是必須支援標準輸入輸出(STDIN和STDOUT);
- Step2:開發你的前端程式,也就是html/css/js之類的,編寫WebSocket Client連線程式碼,接收服務端的資料,如果有必要,還需要將使用者的輸入傳送給伺服器;
- Step3:將你的前端程式檔案(html等)放到伺服器(比如Linux)的某個目錄中,這裡以‘usr/local/websocketj/html’為例,其他平臺類似;
- Step4:啟動websocketj,指定啟動引數:‘websocketj --wsport=8081 --ssport=8082 --staticDir=/usr/local/websocketj/html/ yourprogram args...’;
- Step5:開啟瀏覽器,在位址列中輸入http://ip:8082/,會出現一個預設首頁,websocketj啟動成功了!
下面是啟動引數說明:
--wsport:WebSocket伺服器的工作埠號;
--ssport:靜態web伺服器的工作埠號;
--staticDir:靜態資源存放的目錄,類似tomacat的webapps目錄,存放一些靜態檔案,比如html、css以及js等,可以通過--ssport埠訪問它;
Yourprogram args:你編寫的支援STDIN和STDOUT服務端程式,後面可以攜帶引數。這跟正常啟動命令列類似。
NOTE:正常啟動websocketj之後,訪問8082埠(比如http://192.168.3.73:8082/)可以看到websocketj自帶的預設首頁。
websocketj類似一個處於瀏覽器和應用程式之間的橋樑,它能夠hook程式的inputstream和outputstream,使用WebSocket技術將這兩個stream重新定向到遠端的web瀏覽器。
整個結構非常簡單,一看就懂。下面舉一個簡單的例子,服務端使用bash shell編寫一個定時輸出系統時間的指令碼,前端建立一個html檔案,編寫js使用WebSocket實時接收shell指令碼的輸出,並將其顯示在瀏覽器頁面中。
bash shell(檔名show_time):
#! /bin/bash
while [ true ] do echo "time from linux server:"$(date +%X) sleep 1 done exit 0
html(檔名show_time.html):
<script>
// helper function: log message to screen function print_log(msg) { document.getElementById('msg').textContent = msg; } function print_output(output) { document.getElementById('output').textContent = output; } // setup websocket with callbacks var host = "ws://192.168.3.246:8081/"; var ws = new WebSocket(host); ws.onopen = function() { print_log("Connected To WebSocket Server: => " + host); }; ws.onclose = function() { print_log('Disconnected'); }; ws.onmessage = function(event) { print_output(event.data); }; </script>
將show_time.html檔案放在linux某個目錄中,啟動websocketj:websocketj --wsport=8081 --ssport=8082 --staticDir=/usr/local/websocketj/html ./show_time。然後在瀏覽器中訪問http://192.168.3.246:8082/show_time.html,頁面中實時顯示Linux中的時間,該text來自於bash shell指令碼的STDOUT。
這裡以我電腦上Windows 10中安裝的git cmd為例子,演示如何在瀏覽器中操作git cmd client。由於這裡我們直接使用現有的git cmd程式,所以不需要再編寫服務端程式,只需要編寫前端html頁面來接收輸出和模擬輸入。html(git_cmd.html)頁面在此省略,將該git_cmd.html檔案放在windows某個目錄中E:\codes\git\websocketj\html,啟動websocketj:websocketj --wsport=8081 --ssport=8082 --staticDir=E:\codes\git\websocketj\html C:\Program Files\Git\git-cmd.exe。然後在瀏覽器中訪問http://192.168.3.74:8082/git_cmd.html,輸入git命令,得到輸出:
在Linux中有一個命令來監控系統資源使用情況,比如CPU、網路等。執行‘vmstat 1’命令,程式會在控制檯終端中每隔1秒輸出當前系統狀態:
現在我們使用websocketj將以上輸出重定向到瀏覽器中,並在瀏覽器中使用js控制元件將這些資料視覺化顯示。由於這裡我們使用現成的Linux命令(vmstat 1),因此不需要我們編寫服務端程式,只需要前端html顯示檔案即可。這裡前端我使用了第三方js控制元件,專門用來視覺化這種監控型的資料:http://smoothiecharts.org/。具體程式碼就不放這這裡了,感興趣可以點選官網。下面是最終效果圖:
目前能想到以下功能可以完善:
(1)支援前端隨機啟動指定服務端程式。目前只能啟動一個程式,並且是在websocketj啟動的時候當作引數傳進去的,所有連線的前端只能看到這一個程式的輸入輸出;完善後可以在前端指定要開啟的程式,不同的前端關聯不同的輸入輸出;
(2)前端在進行WebSocket連線時,需要認證。目前所有連線均可接入並關聯到程式的輸入輸出,完善後,只有授權後的連線可以介入。
(3)waiting your passion and brightness.
歡迎各種PR和Issues,Fork websocketj on github
前面一直說這個東西非常簡單,你以為真的嗎?非也,WebSocket這塊採用了第三方開源WebSocket庫,詳細原始碼參見這裡:https://github.com/TooTallNate/Java-WebSocket。這個開源庫可以非常簡單地建立WebSocket伺服器可以WebSocket客戶端。
import java.net.InetSocketAddress; import org.java_websocket.WebSocket; import org.java_websocket.handshake.ClientHandshake; import org.java_websocket.server.WebSocketServer; public class SimpleServer extends WebSocketServer { public SimpleServer(InetSocketAddress address) { super(address); } @Override public void onOpen(WebSocket conn, ClientHandshake handshake) { conn.send("Welcome to the server!"); //This method sends a message to the new client broadcast( "new connection: " + handshake.getResourceDescriptor() ); //This method sends a message to all clients connected System.out.println("new connection to " + conn.getRemoteSocketAddress()); } @Override public void onClose(WebSocket conn, int code, String reason, boolean remote) { System.out.println("closed " + conn.getRemoteSocketAddress() + " with exit code " + code + " additional info: " + reason); } @Override public void onMessage(WebSocket conn, String message) { System.out.println("received message from " + conn.getRemoteSocketAddress() + ": " + message); } @Override public void onMessage( WebSocket conn, ByteBuffer message ) { System.out.println("received ByteBuffer from " + conn.getRemoteSocketAddress()); } @Override public void onError(WebSocket conn, Exception ex) { System.err.println("an error occured on connection " + conn.getRemoteSocketAddress() + ":" + ex); } @Override public void onStart() { System.out.println("server started successfully"); } public static void main(String[] args) { String host = "localhost"; int port = 8887; WebSocketServer server = new SimpleServer(new InetSocketAddress(host, port)); server.run(); } }
程式碼風格和JS一致,用起來非常方便。除了服務端之後,用它還可以快速建立WebSocket客戶端,這樣你就可以模擬瀏覽器進行WebSocket連線了。另外,細心的朋友可能會發現,websocketj是模仿另外一個Go語言版本的websocketd,參見這裡:https://github.com/joewalnes/websocketd/。這個功能更多,我只是看了一下websocketd的功能,至於實現,並沒有參考,對於WebSocket這塊,它也是引用的第三方開源庫Go語言版本。
使用git clone命令將原始碼clone到本地硬碟目錄後,
Windows:
直接使用eclipse匯入maven專案;
Linux:
Linux編譯和執行比較麻煩,需要增加-Djava.ext.dirs=引數引用jar包,並且只需要編譯根目錄中sources.build這個檔案,裡面存放各種原始檔列表。
Linux中編譯:javac -Djava.ext.dirs=../libs/ @sources.build
Linux中執行:java -Djava.ext.dirs=../libs/ -classpath ./src/main/java/ com.zhzhi.websocketj.App --wsport=8081 --ssport=8082 --staticDir=../html/ vmstat 1