Ah… TLDR: I think you don’t need C and D processes. Process A can do all their tasks.
You’d rarely see gen_tcp:recv
being used in real-world Erlang projects. Most of the time you set {active, true}
(risky) or {active, once}
(conservative) or {active, N}
(best performance, but bit more complex) on socket so the process that owns the socket receives TCP data asynchronously from the socket in its mailbox, see Erlang -- gen_tcp.
Blocking send
- I also rarely see people being too worried about it. For UDP I think this is not a problem (worst case packet will be dropped) in general, and in gen_tcp send
s are buffered, see Erlang -- gen_tcp, but if buffer gets full it could block and then it might get tricky yep… There is a send_timeout
option.
And I’d suggest that “radio station streamer” process should not do any networking operation. The cleaner approach is for “radio station” process to kkep the list of “client” process in it’s state and for it to broadcast lists:foreach(fun(Pid) -> Pid ! {data, MediaDataChunk} end, State#state.subscribers)
media data to subscribers (eg, start a timer and broadcast 128kb chunk each second) and let “client” processes write it to their UDP sockets.
You may also make “client” process send “ack” mesages back to radiostation so “station” stops broadcasting to a specific client if there are too much non-acked messages so you don’t run out-of-memory if one of the clients stuck on some blocking operation.
This project, for example, implements somewhat similar structure: https://github.com/seriyps/mtproto_proxy/blob/master/src/mtp_down_conn.erl#L58
There we have small number of mtp_down_conn
processes (representing multiplexed connection to “media source”) which all have large number of mtp_handler
processes (representing individual client connections) connected to them. And it has quite advanced “ack” policy implemented there. Was able to serve few Gb/s with it. It’s not exactly the same, because mtp_down_conn
doesn’t do broadcasting, but it does multiplexing and “routing” (it reads messages from “upstream” socket, figures out to which one of the subscribers it is addressed and sends the media to this particular subscriber and other way around).