Я вижу базовый пример библиотеки Elixir WebSockex здесь, но на самом деле он не объясняет, как я могу открыть мой собственный веб-сокет в Интернете . На этот вопрос есть ответы, объясняющие как общаться с существующим веб-сокетом извне, но я хочу открыть свой собственный веб-сокет. На самом деле я использую websockex как часть приложения Phoenix, так что, возможно, здесь могут помочь кусочки Phoenix?

Я, очевидно, знаю комбинацию ip: port моего приложения Phoenix, поэтому, учитывая это, как мне открыть веб-сокет websockex на этом ip: port? Другими словами, что я должен передать в качестве URL-адреса? в этом базовом примере кода:

defmodule WebSocketExample do
  use WebSockex

  def start_link(url, state) do
    WebSockex.start_link(url, __MODULE__, state)
  end

  def handle_frame({type, msg}, state) do
    IO.puts "Received Message - Type: #{inspect type} -- Message: #{inspect msg}"
    {:ok, state}
  end

  def handle_cast({:send, {type, msg} = frame}, state) do
    IO.puts "Sending #{type} frame with payload: #{msg}"
    {:reply, frame, state}
  end
end

Обратите внимание, что мне нужно открыть необработанный веб-узел, а не канал Phoenix, поскольку потребитель не понимает каналы Phoenix. Если Phoenix может открыть необработанный веб-сокет, я тоже буду рассматривать это решение.

Если ни Phoenix, ни WebSockex не могут помочь, какие у меня варианты?

1
Thomas Browne 1 Мар 2021 в 01:16

2 ответа

Лучший ответ

Websockex - это клиентская библиотека, я не думаю, что в ней есть код для раскрытия веб-сокета. Поскольку вы уже используете Phoenix, вы, вероятно, сможете делать то, что вам нужно, с помощью каналов Phoenix.

Если вы используете cowboy (и, вероятно, так оно и есть, поскольку это значение по умолчанию), то вы также можете использовать его для доступа к необработанному веб-сокету. Однако для этого потребуется немного повозиться с маршрутизацией. Вам нужно будет заменить YourAppWeb.Endpoint ручной настройкой cowboy:

{
  Plug.Cowboy,
  scheme: :http,
  plug: YourAppWeb.Endpoint,
  options: endpoint_options(),
  dispatch: [
    _: [
      # Dispatch paths beginning with /ws to a websocket handler
      {"/ws/[...]", YourApp.WebsocketHandler, []},
      # Dispatch other paths to the phoenix endpoint
      {:_, Plug.Cowboy.Handler, {YourAppWeb.Endpoint, endpoint_options()}}
    ]
  ]
}

Честно говоря, я сделал это только с необработанным plug, поэтому вам может потребоваться преобразовать конечную точку в Plug вместо Phoenix.Endpoint. Затем вам необходимо реализовать YourApp.WebsocketHandler для соответствия API cowboy и выполнить обновление веб-сокета (и обработать отправку / получение сообщений), как описано в в ковбойской документации. Вы также можете увидеть эту суть для более подробного примера.

1
Paweł Obrok 1 Мар 2021 в 19:04

WebSockex реализует множество обратных вызовов, включая, помимо прочего, {{X1 }}. Он удерживает WebSockex.Conn в состоянии и передает его всем обратным вызовам.

WebSockex.Conn - это старый добрый struct < / a> с полем socket.

Таким образом, из любого обратного вызова (я бы сделал это из WebSockex.handle_connect/2) вы можете поделиться этим сокетом с процессом, который в нем нуждается, и использовать его оттуда.


Кроме того, вы можете позаимствовать некоторые внутренние компоненты и проверить, как соединение создается.

Вы увидите, что он использует WebSockex.Conn.new/2, который возвращает инициализированное соединение, которое, в свою очередь, содержит сокет. В этом случае вам придется вручную контролировать процесс, удерживающий сокет.


Сила OSS заключается в том, что все ответы - в одном щелчке мыши от вопросов.

2
Aleksei Matiushkin 1 Мар 2021 в 14:11