Отправка двоичных данных через веб-сокет с помощью cowboy и MessagePack

Я пытаюсь отправить закодированное в MessagePack сообщение от Cowboy в браузер через WebSocket, и полученные данные всегда пусты или недействительны. Я могу отправлять двоичные данные из JS в мой обработчик ковбоев, но не наоборот. Я использую Cowboy 1.0.4 с официальным приложением msgpack-erlang. Я также использую msgpack-lite для моего javascript в браузере.

Примеры:

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:

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

Браузер возвращает ошибку внутри 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...

Если я попытаюсь вывести необработанные данные event.data на консоль, вот что я получаю:

 ArrayBuffer {}

Оно почему-то кажется пустым. Я новичок в erlang и msgpack и не знаю, что происходит. Спасибо за вашу помощь!


person Constantine EmeraldMaster    schedule 22.03.2016    source источник


Ответы (3)


Нашел причину моей проблемы. То, как я пытался декодировать сообщение на клиенте, было неправильным:

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

Правильный путь:

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

Похоже, msgpack-lite не поддерживает двоичный тип. Попробуйте упаковать свои данные в виде строки.

{binary, msgpack:pack("message", [{enable_str, true}])}
person Hynek -Pichi- Vychodil    schedule 22.03.2016
comment
Спасибо, но это не помогает. Я думаю, что основная причина - пустое значение ArrayBuffer. Что-то не так с конфигурацией, но я не знаю что :( - person Constantine EmeraldMaster; 22.03.2016
comment
@ConstantineEmeraldMaster: Вы пробовали и проверяли, что связь через WebSocket работает так, как вы ожидаете? Я подозреваю, что вы вообще ничего не получаете на стороне JS. Просто сначала отправьте строку в распакованном виде. - person Hynek -Pichi- Vychodil; 22.03.2016
comment
Связь работает в обоих направлениях в текстовом режиме, также работает в 1 направлении (от клиента к серверу) в бинарном режиме. JS-клиент не может получать бинарные сообщения с сервера - person Constantine EmeraldMaster; 22.03.2016
comment
@ConstantineEmeraldMaster: В event.data есть контент? - person Hynek -Pichi- Vychodil; 22.03.2016
comment
event.data возвращает пустой ArrayBuffer {} - person Constantine EmeraldMaster; 22.03.2016
comment
@ConstantineEmeraldMaster: Значит, проблема в WebSocket, а не в msgpack. Проверьте, есть ли какой-либо двоичный файл в качестве вывода из msgpack:pack(<<"message">>). Должно быть <<196,7,109,101,115,115,97,103,101>>. Тогда может быть что-то не так в {binary, _} или socket.binaryType = 'arraybuffer'. Я не знаю. Вы должны иметь возможность отправлять обычные двоичные файлы таким образом. - person Hynek -Pichi- Vychodil; 23.03.2016

Использование Uint8Array является допустимым решением проблемы на стороне клиента. На сервере для упаковки строк используйте:

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

Источник : Статья

person JSingh    schedule 17.03.2018