使用Yaws和websockets订阅数据

时间:2012-08-20 13:25:00

标签: erlang websocket yaws

我有一个gen_server与几个硬件传感器说话。此设置工作正常。现在我想通过数据的实时可视化来扩展该系统。我想通过websockets将这些数据传递给Web客户端。

因为我可能有几个“听众”,例如有几个人在不同的网络浏览器上可视化这些数据,我正在考虑类似于观察者模式的东西。每次Web客户端要求订阅传感器时,都应将其添加到该传感器的利益相关者列表中。一旦新的传感器数据到达,就应立即将其推送到客户端。

我正在使用雅司快速获得websocket功能。我的问题与雅司病的运作方式有关。在服务器端,我只通过A#arg.clisock值(例如#Port<0.2825>)在连接时“看到”客户端。在下面的代码中,我注册ws_server以在新数据从客户端进入时接收回调。在此之后,雅司似乎只允许我回复进入服务器端的消息。

out(A) ->
  CallbackMod = ws_server,
  Opts = [{origin, "http://" ++ (A#arg.headers)#headers.host}],

  {websocket, CallbackMod, Opts}.

这就是回调模块的样子:

% handle_message(Incoming)
% Incoming :: {text,Msg} | {binary,Msg} | {close, Status, Reason}
handle_message({Type,Data}) ->
  gen_server:cast(?SERVER,{websocket,Data}),
  noreply.

似乎我无法对subscribe <sensor>之类的消息做出反应,并且(在连接时间之后)动态地将此利益相关者添加到观察者列表中。

如何在会话添加和删除我想要收听的传感器期间使用yaws服务器完成向客户端的异步推送。基本上最简单的方法是,如果雅司可以回调handle_message/2,第一个参数为From。否则我需要添加一个ref以保持双方的ref并且每次都将它发送到服务器,似乎我需要保留该信息。

1 个答案:

答案 0 :(得分:2)

当客户端启动websocket连接时,Yaws将启动一个新的gen_server进程来处理客户端和服务器之间的所有通信。 gen_server将所有客户端发送的消息调度到您的回调函数handle_message/1,因此它不仅用于初始连接。

此外,gen_server进程用于将数据从服务器推送到客户端 - 使用yaws_api:websocket_send(Pid, {Type, Data})函数。 Pid参数是websocket gen_server的pid。您的回调模块可以更改为:

handle_message({Type,Data}) ->
      gen_server:cast(?SERVER,{self(), Data}),
      noreply.

这为您的服务器提供了与yaws_api:websocket_send/2一起使用的websocket gen_server的pid。 Data参数包含客户端请求,需要由服务器解析以检查传感器订阅请求并将websocket pid与适当的传感器相关联。