簡體   English   中英

Javascript web sockets 收發二進制數據?

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM