我有一个 gen_server 与多个硬件传感器通信。这个设置工作正常。现在我想通过数据的实时可视化来扩展这个系统。我想通过 websockets 将此数据传递到 Web 客户端。
因为我可能有几个“听众”,例如有几个人在不同的网络浏览器上可视化这些数据,我正在考虑类似于观察者模式的东西。每次网络客户端请求订阅传感器时,都应将其添加到该传感器的利益相关者列表中。一旦新的传感器数据到达,就应该立即将其推送到客户端。
我正在使用 yaws 来快速获取 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>
这样的消息使用react。并(在连接时间之后)动态地将此利益相关者添加到观察者列表中。
如何使用雅司病服务器来完成向客户端异步推送数据和在 session 期间添加和删除我想要监听的传感器。基本上最简单的方法是雅司病可以回电 handle_message/2
第一个参数是 From
。否则我需要添加一个引用以在两侧保留引用并每次将其发送到服务器,看起来我需要保留该信息。
最佳答案
当客户端启动WebSocket连接时,Yaws将启动一个新的gen_server进程来处理客户端和服务器之间的所有通信。
gen_server 将所有客户端发送的消息分派(dispatch)到您的回调函数 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 与适当的传感器相关联。
关于erlang - 使用 Yaws 和 websockets 订阅数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12038546/