Учебное пособие: Отправка бинарных фреймов в 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};
Давайте проанализируем шаг за шагом, что здесь происходит.
- Когда на websocket приходит бинарный фрейм, мы пытаемся распаковать его с помощью msgpack.
- Если пакету msgpack удается успешно распаковать двоичный фрейм в карту, он отображается в оболочке.
- Если распаковка не удалась, мы создаем новую карту с сообщением об ошибке и выводим сообщение об ошибке на экран.
- Мы упаковываем Erlang Map в бинарный фрейм и отправляем обратно клиенту.
Следующим шагом является добавление маршрута для пересылки запросов веб-сокета этому обработчику.
Dispatch = cowboy_router:compile([ {'_', [{"/", hello_handler, []},{"/ws",websocket,[]}]} ]),
Это завершает обработку реализации веб-сокета на стороне сервера.
Мы установим соединение через веб-сокет, используя javascript в браузере. Вы можете взять ссылки из примеров Cowboy, чтобы установить соединение через веб-сокет: https://github.com/ninenines/cowboy/tree/master/examples/websocket
Давайте пройдемся по шагам для отправки бинарных кадров:
- Добавьте библиотеку 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].
Удачного кодирования :)