web-dev-qa-db-fra.com

Envoyer et recevoir des données binaires sur des sockets Web en Javascript?

Est-il possible d'envoyer et de recevoir des données binaires sur des sockets web en Javascript? Pourrais-je, par exemple, implémenter un client SSH à l'aide de sockets Web?

29
Chad Johnson

Le prochain projet ( hybi-07 ) de la spécification WebSockets est en cours d'implémentation dans la plupart des navigateurs et il ajoutera un support binaire intégré au protocole et à l'API.

Cependant, jusque-là, la charge utile WebSockets est codée en UTF-8. Afin d'envoyer des données binaires, vous devez utiliser un moyen de coder les données binaires en UTF-8.

Il existe de nombreuses options, mais voici deux que j'ai utilisées:

UTF-8 :

Vous pouvez réellement encoder un flux d'octets directement en UTF-8.

Le python pour encoder et décoder ressemblerait à quelque chose comme ceci:

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

En 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('');

Notes de codage UTF-8:

  • Pour les données binaires réparties uniformément sur la valeur 0-255, la taille de la charge utile est 50% plus grande que les données binaires brutes.

  • L'émulateur Flash WebSockets web-socket-js peut avoir des problèmes avec l'encodage de 0 (zéro).

Base 64 :

En python:

from base64 import b64encode, b64decode

data = b64encode(buf)    # encode binary buffer to b64

buf = b64decode(data)    # decode b64 to binary buffer

Pour encoder et décoder les messages du côté Javascript:

data = window.btoa(msg)  // Encode to base64

msg = window.atob(data)  // Decode base64
msg.charCodeAt(N)        // Read decode byte at N

Notes de base 64:

  • Les données binaires uniformément réparties (0-255) seront 33% plus grandes que les données brutes.

  • Il y a moins python surcharge latérale pour le codage base64 que pour le codage UTF-8. Cependant, il y a un peu plus de surcharge latérale Javascript pour le décodage base64 (UTF-8 n'a pas besoin d'être décodé dans Javascript puisque le navigateur a déjà converti l'UTF-8 en UTF-16 natif Javascript).

  • Mise à jour : Cela suppose que les données binaires sont codées en une chaîne UTF-8 comme indiqué ci-dessus avec des valeurs de caractères allant de 0 à 255. Plus précisément, window.atob ne prend pas en charge les valeurs de caractères supérieures à 255. Voir ceci bogue mozilla . La même limitation s'applique à Chrome.

websockify :

WebSockify est un proxy/pont qui permet à un navigateur compatible WebSockets de communiquer avec n'importe quel service binaire arbitraire. Il a été créé pour permettre à noVNC de communiquer avec les serveurs VNC existants. websockify utilise le codage/décodage base64 des données binaires et fournit également un websock.js bibliothèque à utiliser en Javascript. Le websock.js possède une API similaire à WebSocket standard, mais elle gère les données binaires de manière transparente et est conçue pour communiquer avec websockify. Avertissement : J'ai créé websockify et noVNC.

client ssh :

Techniquement, vous pouvez implémenter un client ssh de navigateur sur WebSockets (et je l'ai envisagé), cependant, cela nécessitera le chiffrement et le déchiffrement SSH dans le navigateur, ce qui sera lent. Étant donné que WebSockets a un mode WSS chiffré (TLS), il est probablement plus logique de faire du telnet simple sur WebSocket WSS.

En fait, websockify inclut un exemple de client telnet.

Vous lanceriez websockify sur HOSTNAME comme ceci (telnetd vient de krb5-telnetd):

Sudo ./websockify 2023 --web . --wrap-mode=respawn -- telnetd -debug 2023

Accédez ensuite à http://HOSTNAME:2023/wstelnet.html?hostname=HOSTNAME&port=2023

Voir le websockify README pour plus d'informations. Pour utiliser le cryptage WSS, vous devrez créer une clé SSL comme décrit sur la page wiki d'utilisation avancée noVNC

45
kanaka

Une bonne et sûre façon d'envoyer et de recevoir des données binaires est avec base64 ou base128 (où 128 n'a que 1/7 de surcharge au lieu de 1/3).

Oui, un client SSH est possible.

Une preuve en est qu'il existe déjà de nombreuses solutions qui s'exécutent dans les navigateurs courants, mais la plupart d'entre elles ont toujours besoin d'une implémentation côté serveur personnalisée. Vous pouvez regarder ici pour plus d'informations: http://en.wikipedia.org/wiki/Web-based_SSH

9
sra

Hmm, peut-être que WebSockets pourrait en quelque sorte être combiné avec ceci: http://ie.Microsoft.com/testdrive/HTML5/TypedArrays/

1
Chad Johnson

Maintenant, vous pouvez envoyer et recevoir des données binaires facilement, cet article explique beaucoup de réflexions: http://blog.mgechev.com/2015/02/06/parsing-binary-protocol-data-javascript-typedarrays-blobs /

Voici comment je reçois un tableau numpy binaire envoyé avec python (my_nparray.tobytes ()) dans mon navigateur:

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
    });
};

Vous pouvez convertir un tableau tapé en tableau javascript avec ceci:

Array.prototype.slice.call(buffer.slice());
1
Etienne Prothon