Though this question has been asked before, there is no answer there so here goes again.
I have implemented a nice little ping websocket to talk to Python:
defmodule Exwstest.EchoSocket do
@behaviour Phoenix.Socket.Transport
def child_spec(opts) do
# We won't spawn any process, so let's return a dummy task
%{id: Task, start: {Task, :start_link, [fn -> :ok end]}, restart: :transient}
end
def connect(%{params: %{"token" => token}}) do
# Callback to retrieve relevant data from the connection.
# The map contains options, params, transport and endpoint keys.
state = %{number: 1}
{:ok, state}
end
def init(state) do
# Now we are effectively inside the process that maintains the socket.
send(self(), :sendback)
{:ok, state}
end
def handle_in({text, _opts}, state) do
{:reply, :ok, {:text, "#{text} to you too"}, state}
end
def handle_info(:sendback, %{number: number} = state) do
# here look at the push thing in the website
Process.send_after(self(), :sendback, 1000)
{:push, {:text, Integer.to_string(number)}, %{state | number: number + 1}}
end
def handle_info(_, state) do
{:ok, state}
end
def terminate(_reason, _state) do
:ok
end
end
However I want to send messages to it from inside Elixir, and I have no clue how to obtain its pid
because it’s started by my endpoint.ex
:
socket "/echo/:token", Exwstest.EchoSocket
I suppose I could hack around and get init
to send a message to an external process with the pid, but is that the best way?
(for interest here’s the toy python client)
from websockets.sync.client import connect
def hello():
with connect("ws://localhost:4000/echo/token123/websocket") as websocket:
websocket.send("Hello Thomas")
while True:
message = websocket.recv()
print(f"Received: {message}")
# must send ping at least every 60 seconds
if "ping" not in message:
print("Sending ping")
websocket.send("ping!")
if message == "Bye!":
break
print("Connection closed.")
hello()