在Javascript中通过Web套接字发送和接收二进制数据?

时间:2011-04-23 20:42:42

标签: javascript binary bit-manipulation websocket

可以通过Javascript中的Web套接字发送和接收二进制数据吗?例如,我可以使用Web套接字实现SSH客户端吗?

4 个答案:

答案 0 :(得分:45)

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 bug。同样的限制适用于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加密,您需要按照noVNC advanced usage wiki page

中的说明创建SSL密钥

答案 1 :(得分:8)

发送和接收二进制数据的一种好的和安全的方法是使用base64或base128(其中128只有1/7开销而不是1/3)。

是可以使用SSH客户端。

对此的证明是,已经存在许多在常见浏览器中运行的解决方案,但是大多数解决方案仍然需要自定义服务器端实现。 您可以在此处查看更多信息:http://en.wikipedia.org/wiki/Web-based_SSH

答案 2 :(得分:1)

嗯,也许WebSockets可能会以某种方式与此结合:http://ie.microsoft.com/testdrive/HTML5/TypedArrays/

答案 3 :(得分:1)

现在您可以轻松地发送和接收二进制数据,本文解释了许多想法:http://blog.mgechev.com/2015/02/06/parsing-binary-protocol-data-javascript-typedarrays-blobs/

以下是我在浏览器中接收使用python(my_nparray.tobytes())发送的二进制numpy数组的方法:

Path.Combine(FileSystem.Current.LocalStorage.Path, "file.xml")

您可以使用以下方法将类型化数组转换为javascript数组:

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