Создание клиента Channels
Исходный кодКлиентские библиотеки для Phoenix Channels уже существуют на нескольких языках, но если вы хотите написать собственную, это руководство поможет вам начать. Оно также может пригодиться для ручного тестирования с помощью клиента WebSocket.
Обзор
Поскольку WebSocket — двунаправленный протокол, сообщения могут передаваться в любом направлении в любое время. Поэтому клиенты обычно используют обратные вызовы для обработки входящих сообщений по мере их поступления.
Чтобы начать отправлять и получать сообщения, клиент должен присоединиться как минимум к одной теме. При этом с помощью одного и того же соединения можно присоединиться к любому количеству тем.
Подключение
Чтобы установить WebSocket-соединение с Phoenix Channels, сначала обратите внимание на объявление socket в модуле приложения Endpoint. Например, если вы видите: 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.
Конкретная функция connect/3 в модуле сокета приложения может ожидать или требовать другие параметры или заголовки (в приведённом выше примере — MyAppWeb.MobileSocket.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должно быть сериализуемым (обычно сериализуемым в JSON — это зависит от конфигурации Socket) и передаётся как второй аргумент функции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, может обрабатывать событие 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"}]
© 2014 Chris McCord
Licensed under the MIT License.
https://phoenix.hexdocs.pm/writing_a_channels_client.html