Websocket 如何在Phoenix中通过客户端订阅特定响应来构建web套接字服务器?

Websocket 如何在Phoenix中通过客户端订阅特定响应来构建web套接字服务器?,websocket,elixir,phoenix-framework,Websocket,Elixir,Phoenix Framework,我正在开发一个web套接字服务器,我需要使用Phoenix框架向我的客户端发送实时消息 我的web套接字服务器的基本思想是,一个客户端可以订阅某种类型的信息,并期望只接收它,其他客户端永远不会接收它,除非他们也订阅了它,相同的信息会实时广播到订阅它的每一个(并且只有一个)客户端 此外,这些信息在类别和子类别中分开,向下分为4个级别的类别 例如,假设我有两种类别信息CatA,和CatB,每个类别都可以有子类别,所以CatA可以有CatA.SubCatA和CatA.SubCatB子类别,每个子类别也

我正在开发一个web套接字服务器,我需要使用Phoenix框架向我的客户端发送实时消息

我的web套接字服务器的基本思想是,一个客户端可以订阅某种类型的信息,并期望只接收它,其他客户端永远不会接收它,除非他们也订阅了它,相同的信息会实时广播到订阅它的每一个(并且只有一个)客户端

此外,这些信息在类别和子类别中分开,向下分为4个级别的类别

例如,假设我有两种类别信息
CatA
,和
CatB
,每个类别都可以有子类别,所以
CatA
可以有
CatA.SubCatA
CatA.SubCatB
子类别,每个子类别也可以有其他子类别,等等

这些信息由服务生成,每个根类别一个(它们也处理子类别的所有信息),因此我们有
CatAService
CatBService
。这些服务需要在服务器启动时运行,始终生成新信息并将其广播给订阅它的任何人

现在,我的客户机将尝试订阅这些信息,目前我的解决方案是为每种信息类型提供一个通道,这样客户机就可以加入一个通道来接收该通道类型的信息

因此,我在js代码中有类似的内容:

let channel = socket.channel("CatA:SubCatA:SubSubCatA", {})
channel.join()
channel.on("new_info", (payload) => { ... }
在这种情况下,我将拥有一个频道,所有对
SubCatA
感兴趣的
SubCatA
客户都可以从
CatA
加入,还有一个
CatA
服务,该服务将生成并广播其所有子类别的信息,依此类推

我不确定我是否能够准确地解释我想要什么,但是如果有些事情不清楚,请告诉我什么,这样我才能更好地解释它。此外,我制作了这个(非常糟糕的)图像,作为所有沟通将如何发生的示例

另外,请注意,我只能为每个类别设置一个频道,并为加入该类别频道的每个人广播所有子类别信息,但我非常关心性能和网络带宽,因此我的目标是仅将信息发送给请求该信息的客户端

在这里做一些测试,似乎如果客户端按照上面的js代码所示加入通道,我可以这样做:

MyServerWeb.Endpoint.broadcast "CatA:SubCatA:SubSubCatA", "new_info", message
该客户机(以及所有其他收听该频道的客户机,但只有在那时)才会收到该消息

因此,我的问题分为两个部分,一个是更一般的问题,即实现上述目标的正确方法是什么

第二个问题是我已经提出的解决方案是否是解决这个问题的好方法,因为我不确定字符串“CatA:SubCatA:SubSubCatA”的长度在服务器解析它时是否会产生开销,或者是否存在我不知道的其他限制


谢谢

您必须为每类客户端创建单独的频道,并且根据您获得的ID,您可以在检查加入频道的客户端后广播消息

 def join("groups:" <> group_slug, _params, socket) do
%{team_id: team_id, current_user: user} = socket.assigns

case Repo.get_by(Group, slug: group_slug, team_id: team_id) do
  nil ->
    {:error, %{message: "group not found"}}
  group ->
    case GroupAuthorization.can_view?(group.id, user.id) do
      true ->
        messages = MessageQueries.group_latest_messages(group.id, user)
        json = MessageView.render("index.json", %{messages: messages})
        send self(), :after_join
        {:ok, %{messages: json}, assign(socket, :group, group)}
      false ->
        {:error, %{message: "unauthorized"}}
    end
end
def join(“组:组、参数、套接字)do
%{team\u id:team\u id,当前用户:user}=socket.assignments
案例回购。通过(组,slug:Group\u slug,team\u id:team\u id)完成
零->
{:错误,%{消息:“找不到组”}
组->
案例组授权。可以查看?(group.id,user.id)吗
正确->
messages=messagequerys.group\u最新消息(group.id,用户)
json=MessageView.render(“index.json”,%{messages:messages})
发送self(),:在加入后
{:好,%{messages:json},分配(套接字,:组,组)}
错误->
{:错误,%{消息:“未经授权”}
结束
结束
结束

这是仅向已订阅并加入组的组中的用户发送消息的示例。希望这有帮助