本篇文章沒有太多的源碼,主要講一下實現思路和技術原理
當使用Xshell或者SecureCRT終端工具時,我的所有文件傳輸工作都是通過lrzsz
來完成的,主要是因為其簡單方便,不需要額外打開sftp之類的工具,通過命令就可輕松搞定,在用了WebSSH之后一直在想,這么便捷的操作WebSSH能夠實現嗎?
答案是肯定的,能實現!這要感謝這個古老的文件傳輸協議:zmodem
zmodem采用串流的方式傳輸文件,是xmodem和ymodem協議的改良進化版,具有傳輸速度快,支持斷點續傳、支持完整性校驗等優點,成為目前最流行的文件傳輸協議之一,也被眾多終端所支持,例如Xshell、SecureCRT、item2等
優點之外,zmodem也有一定的局限性,其中之一便是只能可靠地傳輸大小不超過4GB的文件,但對於大部分場景下已夠用,超大文件的傳輸一般也會尋求其他的傳輸方式
lrzsz就是基於zmodem協議實現的文件傳輸,linux下使用非常方便,只需要一個簡單的命令就可以安裝,例如centos系統安裝方式如下
yum install lrzsz
安裝完成后就可以通過rz
命令上傳文件,或者sz
命令下載文件了,這么說上傳或下載其實不是很准確,在zmodem協議中,使用receive接收和send發送來解釋更為准確,無論是receive還是send都是由服務端來發起的
rz
的意思為recevie zmodem,服務端來接收數據,對於客戶端來說就是上傳
sz
的意思是send zmodem,服務端來發送數據,對於客戶端來說就是下載
文件的傳輸需要服務端和客戶端都支持zmodem協議,服務端通過安裝lrzsz實現了對zmodem協議的支持,Xshell和SecureCRT也支持zmodem協議,所以他們能通過rz或sz命令實現文件的上傳和下載,那么Web瀏覽器要如何支持zmodem協議呢?
我們所使用的終端工具xterm.js在3.x版本提供過zmodem擴展插件,但很可惜在4.x版本中已經停止支持了,還好給xterm.js提供zmodem擴展插件的作者開源了一個項目:zmodemjs,用來提供瀏覽器Web對zmodem協議的支持,且能很好的跟xterm.js工具相結合,有了zmodemjs我們就可以通過瀏覽器與終端交互,調用系統rzsz命令實現文件上傳下載了
需要注意的是zmodem是個二進制協議,只支持二進制流,所以通過websocket傳輸的數據必須是二進制的,在django的channel中可以通過指定發送消息的類型為bytes_data
來實現websocket傳輸二進制數據,這是后端實現的核心
websocket.send(bytes_data=data)
配合zmodemjs的前端實現,最終的效果如下
當我完成了Web上使用rzsz上傳下載文件功能后,遇到了一個棘手的問題,無論是監控還是錄像,在sz下載時會將下載的文件二進制顯示在屏幕上,這主要是因為通過zmodemjs可以解析webssh中的二進制文件流為文件,而監控和錄像不行解析,這就需要監控和錄像時過濾掉文件二進制流,起初我想通過分析二進制流來判斷這段流究竟是文件還是文本,但最后發現無法准確識別,一個稍微靠譜的方法是對binary流進行decode解碼,但不能保證100%准確
又深入研究了zmodem協議是如何實現識別的,發現了zmodem的實現原理
在服務器上執行sz命令后,會先輸出**B00000000000000
這樣的內容,標識文件下載開始,當文件下載結束后會輸出OO
,取這兩個特殊標記之間的二進制流組合成文件,就是要下載的完整文件
rz命令類似,會在開始時輸出rz waiting to receive.**0100000023be50
標記,知道了這個規則,就只需要在發送給監控和錄像的數據中去除sz標記之間的內容就可以了,問題完美解決,算是給WebSSH系列畫上了句號
相關文章推薦閱讀: