【发布时间】:2011-08-11 15:04:58
【问题描述】:
可以在 Javascript 中通过 Web 套接字发送和接收二进制数据吗?例如,我可以使用 Web 套接字实现 SSH 客户端吗?
【问题讨论】:
-
乍得,你的问题得到解答了吗?如果可以,您能否选择您认为最好的答案,或者如果没有,您能否就您仍在寻找的内容提供反馈?
标签: javascript binary bit-manipulation websocket
可以在 Javascript 中通过 Web 套接字发送和接收二进制数据吗?例如,我可以使用 Web 套接字实现 SSH 客户端吗?
【问题讨论】:
标签: javascript binary bit-manipulation websocket
发送和接收二进制数据的一种安全的好方法是使用 base64 或 base128(其中 128 的开销仅为 1/7 而不是 1/3)。
是的,可以使用 SSH 客户端。
这方面的一个证据是,已经有很多解决方案可以在普通浏览器中运行,但其中大多数仍然需要自定义服务器端实现。 您可以在这里查看更多信息:http://en.wikipedia.org/wiki/Web-based_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(零)时遇到问题。
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%。
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 编码/解码,还提供了一个 websock.js 库以用于 Javascript。 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 密钥
【讨论】:
嗯,也许 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());
【讨论】: