查看源代码 编写 Channels 客户端
Phoenix Channels 的客户端库已经存在于 多种语言 中,但如果你想自己编写一个,本指南可以帮助你入门。它也可能作为使用 WebSocket 客户端进行手动测试的指南。
概述
由于 WebSockets 是双向的,消息可以在任何时间以任何方向流动。因此,客户端通常使用回调来处理传入的消息,无论何时它们到来。
客户端必须至少加入一个主题才能开始发送和接收消息,并且可以使用同一个连接加入任意数量的主题。
连接
要建立与 Phoenix Channels 的 WebSocket 连接,首先请注意应用程序的 Endpoint
模块中的 socket
声明。例如,如果你看到:socket "/mobile", MyAppWeb.MobileSocket
,则初始 HTTP 请求的路径为
[host]:[port]/mobile/websocket?vsn=2.0.0
传递 &vsn=2.0.0
指定 Phoenix.Socket.V2.JSONSerializer
,它内置于 Phoenix 中,并期望以列表形式接收和返回消息。
你还需要包含 将 HTTP 请求升级到 WebSocket 连接的标准标头字段,或使用一个为你处理此操作的 HTTP 库;在 Elixir 中,mint_web_socket 是一个例子。
应用程序的套接字模块(在上例中为 MyAppWeb.MobileSocket.connect/3
)中特定的 connect/3
函数可能期望或需要其他参数或标头。
消息格式
消息格式由为应用程序配置的序列化器决定。在这些示例中,假设使用 Phoenix.Socket.V2.JSONSerializer
。
客户端发送到 Phoenix Channel 的消息的一般格式如下
[join_reference, message_reference, topic_name, event_name, payload]
join_reference
也由客户端选择,也应该是一个唯一的值。它只需要在"phx_join"
事件中发送;对于其他消息,它可以为null
。它用作来自服务器的push
消息的消息引用,这意味着这些消息不是对特定客户端消息的回复。例如,想象一下类似“新用户刚刚加入聊天室”这样的内容。message_reference
由客户端选择,应该是一个唯一的值。服务器将其包含在回复中,以便客户端知道回复是针对哪条消息的。topic_name
必须是套接字端点已知的主题,并且客户端必须加入该主题才能在其上发送任何消息。event_name
必须与服务器通道模块中的handle_in
函数的第一个参数匹配。payload
应该是一个映射,并作为该handle_in
函数的第二个参数传递。
每个 Phoenix 应用程序都理解三个事件。
首先,phx_join
用于加入一个通道。例如,要加入 miami:weather
通道
["0", "0", "miami:weather", "phx_join", {"some": "param"}]
其次,phx_leave
用于离开一个通道。例如,要离开 miami:weather
通道
[null, "1", "miami:weather", "phx_leave", {}]
第三,heartbeat
用于维护 WebSocket 连接。例如
[null, "2", "phoenix", "heartbeat", {}]
heartbeat
消息仅在没有其他消息发送时才需要,并防止 Phoenix 关闭连接;确切的 :timeout
在应用程序的 Endpoint
模块中配置。
其他允许的消息取决于 Phoenix 应用程序。
例如,如果为 miami:weather
提供服务的 Channel 可以处理 report_emergency
事件
def handle_in("report_emergency", payload, socket) do
MyApp.Emergencies.report(payload) # or whatever
{:reply, :ok, socket}
end
...客户端可以发送
[null, "3", "miami:weather", "report_emergency", {"category": "sharknado"}]