我有一个Cowboy websocket服务器,我想注册一个通过websocket发送内容的gen_event处理程序。我还需要能够使用websocket_handle/3
回复常规同步请求。我没有在cowboy_http_websocket_handler.erl中看到任何明显的内容,cowboy_http_websocket:websocket_send/3未导出。我错过了通过开放套接字发送内容的简单方法吗?
答案 0 :(得分:3)
在the example websocket handler中,websocket_info / 3用于发送这样的内容。将websocket的init代码中的gen_event:add_sup_handler/3与websocket_info / 3结合起来。保持连接的pid处于处理程序的状态,只发送带有异步事件的消息。
答案 1 :(得分:3)
@nmichaels的答案指出我正确的方向,我在牛仔应用程序中成功使用gen_event将内部消息发送到websocket_info。但答案有点过时了,牛仔已经发生了很大变化,所以我想补充一下,并提供适用于最新牛仔版本的解决方案。希望这将有助于一些新的Erlang和牛仔。
为了在牛仔中实现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在全局事件中注册的事件。就是这样。
OP遇到问题的另一个问题是如何将消息发送到打开的连接和初始化时未知pid的连接。要解决此问题,您可以使用pg2在通道下注册进程ID。它是用于修改PID的非常有用的模块。所以上面的代码可以转换成类似的东西
[H|T] = pg2:get_members(Name)
gen_event: notify(global:whereis_name(my_events),{event_name, H}).
通过这种方式,您可以将消息发送到特定的pid,并通过扩展名发送到特定的套接字。