Another way to implement an asynchronous TCP listener is supervisor_bridge
.
Here is the code I wrote to show this (not verified):
-module(connection_bridge). -behaviour(supervisor_bridge). % supervisor_bridge export -export([init/1, terminate/2]). % internal proc_lib:start_link -export([accept_init/3]). %% Port: see gen_tcp:listen(Port, _). %% Options: see gen_tcp:listen(_, Options). %% ConnectionHandler: Module:Function(Arguments)->pid() or fun/0->pid() %% ConnectionHandler: return pid that will receive TCP messages init({Port, Options, ConnectionHandler}) -> case gen_tcp:listen(Port, Options) of {ok, ListenSocket} -> {ok, ServerPid} = proc_lib:start_link(?MODULE, accept_init, [self(), ListenSocket, ConnectionHandler], 1000), {ok, ServerPid, ListenSocket}; OtherResult -> OtherResult end. terminate(_Reason, ListenSocket) -> gen_tcp:close(ListenSocket). accept_init(ParentPid, ListenSocket, ConnectionHandler) -> proc_lib:init_ack(ParentPid, {ok, self()}), accept_loop(ListenSocket, ConnectionHandler). accept_loop(ListenSocket, ConnectionHandler) -> case gen_tcp:accept(ListenSocket) of {ok, ClientSocket} -> Pid = case ConnectionHandler of {Module, Function, Arguments} -> apply(Module, Function, Arguments); Function when is_function(Function, 0) -> Function() end, ok = gen_tcp:controlling_process(ClientSocket, Pid), accept_loop(ListenSocket, ConnectionHandler); {error, closed} -> error({shutdown, tcp_closed}); {error, Reason} -> error(Reason) end.
Much easier to understand than my other answer. connection_bridge
can be expanded to support UDP and SCTP.
Pindatjuh
source share