我有一个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并且每次都将它发送到服务器,似乎我需要保留该信息。
答案 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与适当的传感器相关联。