Skip to content

Instantly share code, notes, and snippets.

@vladimir-vg
Created May 26, 2018 05:54
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save vladimir-vg/eba0284be498b6c25200047f3d9f87ae to your computer and use it in GitHub Desktop.
Save vladimir-vg/eba0284be498b6c25200047f3d9f87ae to your computer and use it in GitHub Desktop.
-module(echo_server).
-behavior(gen_server).
-export([start_link/0]). % supervisor callback
-export([init/1, handle_call/3, handle_cast/2, handle_info/2]). % gen_server callbacks
-export([handler_loop/1]).
start_link() ->
gen_server:start_link({local, ?MODULE}, ?MODULE, [], []).
init([]) ->
self() ! init,
{ok, #{}}.
handle_info(init, #{} = State) ->
{ok, Sock} = gen_tcp:listen(0, [{packet, line}]),
{ok, Port} = inet:port(Sock),
lager:info("~p listen on ~p port.~n", [Sock, Port]),
self() ! accept,
{noreply, State#{sock => Sock, port => Port}};
handle_info(accept, #{sock := Sock} = State) ->
case gen_tcp:accept(Sock, 1000) of
{error, _} -> ok;
{ok, Conn} ->
lager:info("got a new client ~p", [Conn]),
HandlerPid = proc_lib:spawn(?MODULE, handler_loop, [#{conn => Conn}]),
gen_tcp:controlling_process(Conn, HandlerPid)
end,
self() ! accept,
{noreply, State};
handle_info(Msg, State) ->
{stop, {unknown_info, Msg}, State}.
handle_call(Call, _From, State) ->
{stop, {unknown_call, Call}, State}.
handle_cast(Cast, State) ->
{stop, {unknown_cast, Cast}, State}.
handler_loop(#{conn := Conn} = State) ->
receive
{tcp_closed, Conn} ->
lager:info("~p closed.~n", [Conn]),
exit(client_closed_connection);
{tcp, Conn, Data} ->
lager:info("~p ~p~n", [Conn, Data]),
gen_tcp:send(Conn, Data),
?MODULE:handler_loop(State)
end.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment