如何使用 Cowboy 通过 Websocket 异步发送数据?

发布于 2024-12-15 18:52:47 字数 593 浏览 1 评论 0原文

我有一个 Cowboy websocket 服务器,我想注册一个 gen_event 通过 websocket 发送内容的处理程序。我还需要能够使用 websocket_handle/3 回复常规同步请求。我在 cowboy_http_websocket_handler.erl 和 < a href="https://github.com/extend/cowboy/blob/master/src/cowboy_http_websocket.erl" rel="noreferrer">cowboy_http_websocket:websocket_send/3 未导出。我是否缺少一种通过开放套接字发送内容的简单方法?

I have a Cowboy websocket server and I'd like to register a gen_event handler that sends something over the websocket. I also need to be able to reply to regular synchronous requests with websocket_handle/3. I didn't see anything obvious in cowboy_http_websocket_handler.erl and cowboy_http_websocket:websocket_send/3 isn't exported. Am I missing an easy way to send something over an open socket?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

清泪尽 2024-12-22 18:52:47

@nmichaels 的回答为我指明了正确的方向,我在牛仔应用程序中成功使用 gen_event 将内部消息发送到 websocket_info。但答案有点过时,牛仔已经改变了很多,所以我想添加它并提供适用于最新牛仔版本的解决方案。希望这会对 Erlang 和牛仔新手有所帮助。

在cowboy中实现gen_event需要三个步骤

  • 启动gen_event并注册处理程序

    start(_Type, _Args) ->;
    调度=cowboy_router:编译(wrinqle_routes:routes_configuration()),
    {ok, _} = 牛仔:start_http(http, 100, [{端口, 3000}],
                                [{env, [{dispatch, 调度}]}]),
      pg2:开始(),
    
      gen_event:开始({全局,my_events}),
      gen_event:add_handler({全局,my_events},my_event_handler,[])。
    

这里我已经全局注册了名为 my_events 的事件(注意:您也可以在本地注册事件)并在模块 my_event_handler 中添加了处理程序

  • 创建一个事件处理程序.

  • 现在您可以从牛仔中的任何位置通知您的事件处理程序。作为示例,下面的代码从 websocket_handler 引发事件

    <前><代码>{ _,_ }->

    gen_event: 通知(全局:whereis_name(my_events),{event_name,self()}),
    {确定,请求,状态};

所有这些代码所做的就是通知在 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 并扩展到特定的套接字。

@nmichaels answer pointed me in the right direction and I used gen_event successfully in a cowboy app to send internal messages to the websocket_info. But the answer is a bit dated and cowboy has changed a lot so I would like to add to it and provide a solution that works on the latest cowboy version. Hopefully this will help some one new to Erlang and cowboy.

There are three steps needed in order to implement a gen_event in cowboy

  • Start the gen_event and register you handlers

    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,[]).
    

Here I have registered the event called my_events globally (note: you can register the events locally as well) and added handler in the module my_event_handler

  • Create an event handler.

  • Now you can notify your event handler of the events from anywhere in cowboy. As an example the code below raises events from the websocket_handler

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

All this code is doing is notifying the event registered under my_events globally of the event. That's it.

Another problem the OP had trouble with was how to send messages to open connections and connections for which pid is not known at the time of initialization. To solve this problem you can make use of pg2 which registers process id under channels. It is a very useful module for manging PIDs. So the above code can be transformed to something like this

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

And this way you can send message to a particular pid and by extension to a particular socket.

示例 websocket 处理程序中,websocket_info/3 用于发送像这样的东西。将 websocket 初始化代码中的 gen_event:add_sup_handler/3 与 websocket_info 结合起来/3。将连接的 pid 保留在处理程序的状态中,并仅发送带有异步事件的消息。

In the example websocket handler, websocket_info/3 is used to send stuff like this. Combine gen_event:add_sup_handler/3 in the websocket's init code with websocket_info/3. Keep the pid of the connection in the handler's state and just send a message with the asynchronous event.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文