Учебное пособие: Отправка бинарных фреймов в Cowboy WebSocket

Использование msgpack для отправки бинарных фреймов в WebSocket — Cowboy (HTTP-сервер на основе Erlang)

Если вы не знакомы с этим фреймворком, вы можете начать с другой моей статьи о настройке Erlang,Cowboy на Amazon EC2: https://medium.com/@tojeevansingh/when-i-stopped-scripting-and-started- внедрение-начало-с-установки-erlang-cowboy-on-amazon-fca282dc8ee

Давайте начнем с добавления зависимости: msgpack в наш Makefile.

DEPS = cowboy msgpack

Скрипт «erlang.mk» автоматически определяет новую зависимость и соответствующим образом настраивает ее при выполнении следующей команды.

make deps

Теперь давайте создадим модуль для обработки подключения к веб-сокету, используя доступный шаблон, предоставленный Cowboy.

make new t=cowboy.ws n=websocket

Это создаст новый файл с именем websocket.erl в каталоге src с базовой схемой для определения реализации веб-сокета. Подробнее о содержимом этого файла можно прочитать в руководстве пользователя Cowboy: https://ninenines.eu/docs/en/cowboy/2.2/guide/ws_handlers/

Внесите следующие изменения в «websocket.erl» для обработки двоичных фреймов.

websocket_handle({binary,Data},State) ->
 {Status,Message} = msgpack:unpack(Data,[{unpack_str,as_binary}]),
 Map =
  case Status of
   ok ->
    io:format("Received Binary Frame: ~p~n",[Message]),
    Message;
   error ->
    io:format("Error While Unpacking Binary Frame: ~p~n",[Message]),  
    #{error => <<"Unpacking Failed">>}
  end,
 Binary = msgpack:pack(Map,[{pack_str,from_binary}]),
 {reply,{binary,Binary},State};

Давайте проанализируем шаг за шагом, что здесь происходит.

  1. Когда на websocket приходит бинарный фрейм, мы пытаемся распаковать его с помощью msgpack.
  2. Если пакету msgpack удается успешно распаковать двоичный фрейм в карту, он отображается в оболочке.
  3. Если распаковка не удалась, мы создаем новую карту с сообщением об ошибке и выводим сообщение об ошибке на экран.
  4. Мы упаковываем Erlang Map в бинарный фрейм и отправляем обратно клиенту.

Следующим шагом является добавление маршрута для пересылки запросов веб-сокета этому обработчику.

Dispatch = cowboy_router:compile([
  {'_', [{"/", hello_handler, []},{"/ws",websocket,[]}]}
]),

Это завершает обработку реализации веб-сокета на стороне сервера.

Мы установим соединение через веб-сокет, используя javascript в браузере. Вы можете взять ссылки из примеров Cowboy, чтобы установить соединение через веб-сокет: https://github.com/ninenines/cowboy/tree/master/examples/websocket

Давайте пройдемся по шагам для отправки бинарных кадров:

  1. Добавьте библиотеку javascript msgpack в html. Хорошей практикой является добавление всех javascript-библиотек в конце тега body.
<script src="https://rawgit.com/kawanet/msgpack-lite/master/dist/msgpack.min.js"</script>

2. Определите «binaryType» для веб-сокета при инициализации объекта веб-сокета. Тип по умолчанию — «blob», если вы его не объявляете.

var websocket = new WebSocket("ws://localhost:8080/ws");
websocket.binaryType = 'arraybuffer';

3. Чтобы отправить двоичный фрейм, закодируйте объект json с помощью msgpack.

websocket.send(msgpack.encode({"foo":"bar"}));

Если вы проверите свою оболочку Erlang, она зарегистрирует получение двоичного кадра.

4. Для декодирования бинарного кадра, полученного при подключении к веб-сокету.

function onMessage(evt){
  var json = msgpack.decode(new Uint8Array(evt.data));
  console.log(json);
}

Если вы проверите консоль браузера с помощью инструментов отладчика, вы увидите, что она регистрирует отправленный вами json — {"foo":"bar"}

Это все, что нужно для отправки и получения бинарных кадров из клиентского веб-сокета.

Примечания

Cowboy изначально поддерживает бинарные фреймы без msgpack. Вы можете отправлять двоичные кадры в формате json, но это не сжимает размер сообщения в байтах.

Вы можете добавить зависимость «jsx» в свой Makefile для отправки и получения сообщений json на стороне сервера и использовать «TextEncoder»/»TextDecoder» для анализа двоичного json на стороне клиента, но они не поддерживаются в IE.

И последнее замечание: существует еще одна библиотека для установления бинарной связи в формате json между клиентом и сервером — capnproto, которая должна быть более эффективной, чем msgpack. Подробнее об этом можно прочитать здесь https://capnproto.org/

Если у вас есть какие-либо вопросы или проблемы при настройке, отправьте мне электронное письмо по адресу [email protected].

Удачного кодирования :)