如何使用 Phoenix 将消息发送到特定套接字

How to send message to specific socket with Phoenix

我有一些验证套接字:

defmodule Test.UserSocket do
  use Phoenix.Socket

  ## Channels
  channel "user:*", Test.RoomChannel

  def connect(_params, socket) do
    case Phoenix.Token.verify(socket, "user",  _params["token"]) do
          {:ok, uid} ->
            {:ok, assign(socket, :user_id, uid)}
          {:error, _} ->
            :error
     end
  end

 def id(_socket), do: "user:#{_socket.assigns.user_id}"
end

连接后命名为 user:#id

的套接字

根据文档我可以发送断开连接事件 Test.Endpoint.broadcast("users_socket:" <> user.id, "disconnect", %{})

问题:如何通过user:#id将自定义事件发送到套接字,它应该像向特定套接字推送通知一样。

我尝试了 Test.Endpoint.broadcast "user:1", "new:msg", %{user: "SYSTEM", body: "iex"} 但它不起作用,因为我无法在套接字上收听 "new:msg"。

从评论中复制 Chris McCord 的回答:

您可以像您描述的那样在频道上进行。如果您已经在 connect 的套接字上验证并分配了当前用户,则无需在 join/3 中验证。只需根据用户尝试加入的房间检查 socket.assigns.user_id。然后你广播到那个房间Endpoint.broadcast "rooms:1", "new_msg", %{user: "SYSTEM", body: "iex"}

(将答案标记为社区维基,因为如果有人决定对此投票,我不想要代表点数。这不是我的答案:))

Thanks for the answer. So we works only on 'room' bases. And my sources will be like: def join("user:"<> _uid, message, socket) do if _uid == socket.assigns.user_id do {:ok, socket} else {:error, %{reason: "unauthorized"}} end end

您不需要再次验证 userId,因为您已经在 UserSocket#connect 中定义了逻辑,如果用户未通过身份验证,他会收到一条消息说他未获得授权,您可以做的是使用 userId例如检查用户是否有权查看特定频道

def join("rooms:some_private_room", message, socket) do 
  if socket.assigns.user_id do 
    {:ok, socket}
  else 
    # kick him out he is not allowed here
    {:error, %{reason: "unauthorized"}} 
  end 
end