JavascriptでWebソケットを介してバイナリデータを送受信することは可能ですか?たとえば、Webソケットを使用してSSHクライアントを実装できますか?
WebSockets仕様の次のドラフト( hybi-07 )は、ほとんどのブラウザーに実装されており、プロトコルとAPIに組み込みのバイナリサポートが追加されます。
ただし、それまでは、WebSocketペイロードはUTF-8としてエンコードされます。バイナリデータを送信するには、バイナリデータをUTF-8としてエンコードする何らかの方法を使用する必要があります。
多くのオプションがありますが、ここで私が使用した2つがあります。
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(ゼロ)のエンコーディングで問題が発生する可能性があります。
Base 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
Base 64ノート:
均等に分散されたバイナリデータ(0〜255)は、生データより33%大きくなります。
python base64エンコーディングへのサイドオーバーヘッドはUTF-8エンコーディングよりも少なくなります。ただし、base64をデコードするためのJavascriptサイドオーバーヘッドは少し多くなります(UTF-8はブラウザはすでにUTF-8をJavascriptネイティブUTF-16に変換しているため、JavaScript。
Update:これは、バイナリデータが上記のように0〜255の範囲の文字値を持つUTF-8文字列にエンコードされることを前提としています。具体的には、window.atobは255を超える文字値をサポートしていません。この mozillaバグ を参照してください。同じ制限がChromeにも適用されます。
websockify:
WebSockify は、WebSockets対応ブラウザが任意のバイナリサービスと通信できるようにするプロキシ/ブリッジです。 noVNC が既存のVNCサーバーと通信できるようにするために作成されました。 websockifyは、バイナリデータのbase64エンコード/デコードを使用し、Javascriptで使用するためのwebsock.js
ライブラリも提供します。 websock.js
には、通常のWebSocketと同様のAPIがありますが、バイナリデータを透過的に処理し、websockifyと通信するように設計されています。 免責事項:私はwebsockifyとnoVNCを作成しました。
sshクライアント:
技術的には、WebSocketを介してブラウザーのsshクライアントを実装することもできます(私はそれを検討しました)。ただし、ブラウザーでSSHの暗号化と復号化を行う必要があるため、処理が遅くなります。 WebSocketには暗号化された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暗号化を使用するには、 noVNCの高度な使用法のWikiページで説明されているようにSSLキーを作成する必要があります
バイナリデータを送受信する適切で安全な方法の1つは、base64またはbase128を使用することです(128のオーバーヘッドは、1/3ではなく1/7だけです)。
はい、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());