Question

I am using yaws (Erlang framework) for socket communication. I can send message back to the user from server using websocket_send however i need to specify the PID of the user, that means that i can send message back to that user. However, i would like to send message to all connected users. Is there any way to do it?

Was it helpful?

Solution 2

Got it worked !!! Using GProc :)

Gproc is a process dictionary for Erlang, which provides a number of useful features beyond what the built-in dictionary has:

Use any term as a process alias

Register a process under several aliases

Non-unique properties can be registered simultaneously by many processes

QLC and match specification interface for efficient queries on the dictionary

Await registration, let's you wait until a process registers itself

Atomically give away registered names and properties to another process

Counters, and aggregated counters, which automatically maintain the total of all counters with a given name

Global registry, with all the above functions applied to a network of nodes

OTHER TIPS

Every time a websocket connection is established a new gen_server process is created for that connection. Hence each of these servers corresponds to one websocket connection. Thus websocket_send requires the PID of the gen_server.

For sending message to all the connected clients you need to maintain the PIDs of all the gen_servers. This can be done by having your own gen_server or using ets.

Similar to sending the Pid to gen_server you can send the Pid in websocket callback init function

init(Args) ->
  gen_server:cast(?YOURSERVER,{connection_open, self()}),
  {ok, []}.

During termination

terminate(Reason, State) ->
  gen_server:cast(?YOURSERVER,{connection_close, self()}).

Your gen_server handle_cast may look like this

handle_cast({connection_open, Pid}, Pids) ->
      {noreply, [Pid | Pids]};
handle_cast({connection_close, Pid}, Pids) ->
      {noreply, lists:delete(Pid, Pids)};
handle_cast({send_to_all, Msg}, Pids) ->
      [yaws_api:websocket_send(Pid, Msg) || Pid <- Pids, is_process_alive(Pid)],
      {noreply, Pids}.

That will need a comprehensive approach which involves in-memory storage. Forexample, Each user may have a process holding the socket connection and so, you save say, in mnesia, or ets table e.t.c. a record like: #connected_user{pid = Pid,username = Username,other_params = []}.

Later after advancing your perception of this problem, you will move onto session management, how to handle offline messages, and most importantly presence. Anyways, when a message comes in, having the destination username, then you will make a lookup from our table and get the corresponding Pid, and then send it this message, which in turn, it will then send it through its live Web Socket.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top