简体   繁体   English

使用cowboy和MessagePack在websocket上发送二进制数据

[英]Sending binary data over websocket with cowboy and MessagePack

I'm trying to send a MessagePack-encoded message from Cowboy to a browser over WebSocket, and received data is always empty or invalid. 我正在尝试通过WebSocket将来自Cowboy的MessagePack编码消息发送到浏览器,并且接收到的数据始终为空或无效。 I'm able to send binary data from JS to my cowboy handler, but not vice versa. 我能够将JS中的二进制数据发送给我的牛仔处理程序,但反之亦然。 I'm using Cowboy 1.0.4 with official msgpack-erlang application. 我正在使用Cowboy 1.0.4与官方的msgpack-erlang应用程序。 I also use msgpack-lite for my in-browser javascript. 我也使用msgpack-lite作为我的浏览器中的javascript。

Examples: 例子:

websocket_handler : websocket_handler

websocket_handle({text, <<"return encoded">>}, Req, State) ->
    %% sends encoded message to client. Client is unable to decode and fails
    {reply, {binary, msgpack:pack(<<"message">>)}, Req, State};
websocket_handle({binary, Encoded}, Req, State) ->
    %% Works as expected
    lager:info("Received encoded message: ~p", [msgpack:unpack(Encoded)]),
    {ok, Req, State};

JS: JS:

var host = "ws://" + window.location.host + "/websocket";
window.socket = new WebSocket(host);
socket.binaryType = 'arraybuffer';
socket.onmessage = function(event) {
    var message = msgpack.decode(event.data);
    console.log(message);
};

Browser returns an error inside msgpack.min.js: 浏览器在msgpack.min.js中返回错误:

Error: Invalid type: undefined
...ion n(t){var r=i(t),e=f[r];if(!e)throw new Error("Invalid type: "+(r?"0x"+r.toSt...

If I try to output raw event.data to console, here's what I'm getting: 如果我尝试将原始event.data输出到控制台,这是我得到的:

 ArrayBuffer {}

It seems to be empty for some reason. 由于某种原因,它似乎是空的。 I'm new both to erlang and msgpack , and don't know what is going wrong. 我是erlangmsgpack ,不知msgpack什么问题。 Thanks for your help! 谢谢你的帮助!

Found the reason of my problem. 找到了我的问题的原因。 The way how I tried to decode message on the client was wrong: 我尝试在客户端上解码消息的方式是错误的:

socket.onmessage = function(event) {
  var message = msgpack.decode(event.data);
  console.log(message);
};

The right way: 正确的方式:

socket.onmessage = function(event) {
    var raw_binary_data = new Uint8Array(event.data);
    var message = msgpack.decode(raw_binary_data);
    console.log(message);
};

It seems like msgpack-lite doesn't support binary type. 似乎msgpack-lite不支持二进制类型。 Try pack your data as a string. 尝试将数据打包为字符串。

{binary, msgpack:pack("message", [{enable_str, true}])}

Using Uint8Array is a valid solution for client side issue. 使用Uint8Array是客户端问题的有效解决方案。 On server to pack strings use: 在服务器上打包字符串使用:

msgpack:pack(<<"message">>,[{pack_str,from_binary}])

Source : Article 资料来源: 文章

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM