Как я могу отправлять данные асинхронно через веб-сокет с Cowboy? - PullRequest
4 голосов
/ 15 ноября 2011

У меня есть сервер веб-сокета Cowboy , и я хотел бы зарегистрировать обработчик gen_event , который отправляет что-то через веб-сокет.Мне также нужно иметь возможность отвечать на регулярные синхронные запросы с websocket_handle/3.Я не увидел ничего очевидного в cowboy_http_websocket_handler.erl и cowboy_http_websocket: websocket_send / 3 не экспортируется.Мне не хватает простого способа отправить что-то через открытый сокет?

Ответы [ 2 ]

3 голосов
/ 18 ноября 2013

@ nmichaels answer указал мне верное направление, и я успешно использовал gen_event в приложении для ковбоев для отправки внутренних сообщений в websocket_info.Но ответ немного устарел, и ковбой сильно изменился, поэтому я хотел бы добавить к нему и предложить решение, которое работает на последней версии ковбоя.Надеюсь, это поможет кому-то новому для Эрланга и ковбоя.

Для реализации gen_event в ковбое необходимо выполнить три шага

  • Запустить gen_event и зарегистрировать ваши обработчики

    start(_Type, _Args) ->
    Dispatch = cowboy_router:compile(wrinqle_routes:routes_configuration()),
    {ok, _} = cowboy:start_http(http, 100, [{port, 3000}],
                                [{env, [{dispatch, Dispatch}]}]),
      pg2:start(),
    
      gen_event:start({global,my_events}),
      gen_event:add_handler({global,my_events},my_event_handler,[]).
    

Здесь я зарегистрировал событие my_events глобально (примечание: вы также можете зарегистрировать события локально) и добавил обработчик в модуль my_event_handler

  • Создайте обработчик события.

  • Теперь вы можете уведомлять обработчик событий о событиях из любой точки ковбоя.В качестве примера приведенный ниже код вызывает события из websocket_handler

    { _,_ }->
    
       gen_event: notify(global:whereis_name(my_events),{event_name,self()}),
        {ok,Req,State};
    

Все, что делает этот код, - это оповещение о событии, зарегистрированном в my_events, о глобальном событии.Вот и все.

Другая проблема, с которой столкнулся ОП, заключалась в том, как отправлять сообщения об открытых соединениях и соединениях, для которых pid не известен во время инициализации.Для решения этой проблемы вы можете использовать pg2 , который регистрирует идентификатор процесса по каналам.Это очень полезный модуль для управления PID.Таким образом, приведенный выше код может быть преобразован во что-то вроде этого

  [H|T] = pg2:get_members(Name)
  gen_event: notify(global:whereis_name(my_events),{event_name, H}).

И таким образом вы можете отправлять сообщения на определенный pid и, соответственно, на конкретный сокет.

3 голосов
/ 16 ноября 2011

В пример обработчика websocket , websocket_info / 3 используется для отправки подобных вещей. Объедините gen_event: add_sup_handler / 3 в коде инициализации websocket с websocket_info / 3. Держите pid соединения в состоянии обработчика и просто отправьте сообщение с асинхронным событием.

...