[英]Send and receive binary data over web sockets in Javascript?
Javascript web sockets 可以收發二進制數據嗎? 例如,我可以使用 web sockets 實現 SSH 客戶端嗎?
WebSockets規范的下一個草案( hybi-07 )正在大多數瀏覽器中實現,它將為協議和API添加內置的二進制支持。
但是,在此之前,WebSockets有效負載編碼為UTF-8。 為了發送二進制數據,您必須使用某種方式將二進制數據編碼為UTF-8。
有很多選擇,但這里有兩個我用過:
UTF-8 :
您實際上可以將字節流直接編碼為UTF-8。
編碼和解碼的python看起來像這樣:
from codecs import (utf_8_encode, utf_8_decode,
latin_1_encode, latin_1_decode)
utf_8_encode(unicode(buf, 'latin-1'))[0] # encode
latin_1_encode(utf_8_decode(utf8_buf)[0])[0] # decode
在Javascript中:
chr = data.charCodeAt(N) // to 'decode' at position N of the message
// Enocde array of bytes (0-255) to UTF-8
data = array.map(function (num) {
return String.fromCharCode(num); }).join('');
UTF-8編碼說明:
對於在值0-255上均勻分布的二進制數據,有效載荷的大小比原始二進制數據大50%。
Flash WebSockets模擬器web-socket-js可能在編碼0(零)時遇到問題。
基地64 :
在python中:
from base64 import b64encode, b64decode
data = b64encode(buf) # encode binary buffer to b64
buf = b64decode(data) # decode b64 to binary buffer
要在Javascript端編碼和解碼消息:
data = window.btoa(msg) // Encode to base64
msg = window.atob(data) // Decode base64
msg.charCodeAt(N) // Read decode byte at N
基地64筆記:
均勻分布的二進制數據(0-255)將比原始數據大33%。
base64編碼的python端開銷少於UTF-8編碼。 但是,解碼base64會有更多的Javascript側開銷(UTF-8不需要在Javascript中解碼,因為瀏覽器已經將UTF-8轉換為Javascript本機UTF-16)。
更新 :這假設二進制數據被編碼為UTF-8字符串,如上所示,字符值范圍為0-255。 具體來說,window.atob不支持255以上的字符值。請參閱此mozilla錯誤 。 同樣的限制適用於Chrome。
websockify :
WebSockify是一個代理/網橋,允許支持WebSockets的瀏覽器與任意二進制服務進行通信。 創建它是為了允許noVNC與現有VNC服務器通信。 websockify使用二進制數據的base64編碼/解碼,並提供了一個用於Javascript的websock.js
庫。 websock.js
有一個類似於常規WebSocket的API,但它透明地處理二進制數據,旨在與websockify進行通信。 免責聲明 :我創建了websockify和noVNC。
ssh客戶端 :
從技術上講,你可以通過WebSockets實現一個瀏覽器ssh客戶端(我已經考慮過了),但是,這需要在瀏覽器中進行SSH加密和解密,這將很慢。 鑒於WebSockets具有加密的WSS(TLS)模式,通過WebSocket WSS進行普通的telnet可能更有意義。
實際上,websockify包含一個示例telnet客戶端。
您可以像這樣在HOSTNAME上啟動websockify(telnetd來自krb5-telnetd):
sudo ./websockify 2023 --web . --wrap-mode=respawn -- telnetd -debug 2023
然后導航到http://HOSTNAME:2023/wstelnet.html?hostname=HOSTNAME&port=2023
有關更多信息,請參閱websockify README 。 要使用WSS加密,您需要創建一個SSL密鑰,如noVNC高級使用Wiki頁面所述
發送和接收二進制數據的一種好的和安全的方法是使用base64或base128(其中128只有1/7開銷而不是1/3)。
是的,SSH客戶端是可能的。
這方面的證據是,已經有很多解決方案在常見的瀏覽器中運行,但是大多數解決方案仍然需要自定義服務器端實現。 您可以在此處查看更多信息: http : //en.wikipedia.org/wiki/Web-based_SSH
也許,WebSockets可能會以某種方式與此相結合: http : //ie.microsoft.com/testdrive/HTML5/TypedArrays/
現在您可以輕松地發送和接收二進制數據,本文解釋了許多想法: http : //blog.mgechev.com/2015/02/06/parsing-binary-protocol-data-javascript-typedarrays-blobs/
以下是我在瀏覽器中接收使用python(my_nparray.tobytes())發送的二進制numpy數組的方法:
ws = new WebSocket("ws://localhost:51234");
ws.binaryType = 'blob';
var buffer;
ws.onmessage = function (evt) {
var reader = new FileReader();
reader.readAsArrayBuffer(evt.data);
reader.addEventListener("loadend", function(e)
{
buffer = new Uint16Array(e.target.result); // arraybuffer object
});
};
您可以使用以下方法將類型化數組轉換為javascript數組:
Array.prototype.slice.call(buffer.slice());
如果沒有 web 服務器的幫助,您無法在使用 WebSocket 的瀏覽器中實現 SSH 客戶端,該服務器將充當 SSH 客戶端或某種 WebSocket 到 SSH 代理。
WebSocket 協議允許發送任意二進制數據(甚至不是 UTF-8 或 Base-64 編碼)但數據被封裝在格式由 WebSocket 協議定義的幀中(參見RFC6455 )並且與 SSH 協議無關。 這種封裝被 Javascript 隱藏在 web 瀏覽器端,但是接收 WebSocket 連接的服務器接收它並且還必須實現它以便可以建立連接。
因此,可以將 SSH 協議作為 WebSocket 協議的有效載荷進行交換,但不能實現標准的 SSH 客戶端。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.