Consider the following erlang code of a simple echo server:
Echo listener:
-module(echo_listener).
-export([start_link/1]).
-define(TCP_OPTIONS, [binary, {packet, 0}, {reuseaddr, true},
{keepalive, true}, {backlog, 30}, {active, false}]).
start_link(ListenPort) ->
{ok, ListenSocket} = gen_tcp:listen(ListenPort, ?TCP_OPTIONS),
accept_loop(ListenSocket).
accept_loop(ListenSocket) ->
{ok, ClientSocket} = gen_tcp:accept(ListenSocket),
Pid = spawn(echo_worker, usher, [ClientSocket]),
gen_tcp:controlling_process(ClientSocket, Pid),
accept_loop(ListenSocket).
Echo worker:
-module(echo_worker).
-export([echo/1]).
echo(ClientSocket) ->
case gen_tcp:recv(ClientSocket, 0) of
{ok, Data} ->
gen_tcp:send(ClientSocket, Data),
echo(ClientSocket);
{error, closed} ->
ok
end.
Whenever a client socket is accepted, the echo server spawns a echo worker and pass the client socket directly as a function parameter. In the code there is controller_process(), but I have tried the code without calling controlling_process(), it also works.
What is the real purpose of controlling_process()? When is it needed?
Thanks in advance.
Erlang documentation says about gen_tcp:controlling_process/1:
Assigns a new controlling process Pid to Socket. The controlling process is the process which receives messages from the socket. If called by any other process than the current controlling process, {error, not_owner} is returned.
You created listen socket with option {active, false} and you read the socket synchronously with gen_tcp:recv/2 so your code will work even without calling of gen_tcp:controlling_process/1. However if you want to receive data asynchronously you must create listen socket with option {active, true}. In that case owner of accepted connection will receive messages about incoming data. So if you dont call gen_tcp:controlling_process/1 these messages will be sent to listener process instead of worker.