Skip to content

Instantly share code, notes, and snippets.

@cmullaparthi
Created April 16, 2016 05:22
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save cmullaparthi/18ba2219befbf7a3c44c28cab004456f to your computer and use it in GitHub Desktop.
Save cmullaparthi/18ba2219befbf7a3c44c28cab004456f to your computer and use it in GitHub Desktop.
-module(tcp_server).
-behaviour(gen_server).
%% API
-export([start_link/0]).
%% gen_server callbacks
-export([init/1, handle_call/3, handle_cast/2, handle_info/2,
terminate/2, code_change/3]).
-define(SERVER, ?MODULE).
-record(state, {listen_socket}).
%%%===================================================================
%%% API
%%%===================================================================
start_link() ->
gen_server:start_link({local, ?SERVER}, ?MODULE, [], []).
%%%===================================================================
%%% gen_server callbacks
%%%===================================================================
init([]) ->
{ok, Sock} = gen_tcp:listen(12345, [binary, {active, false}]),
self() ! accept_connection,
{ok, #state{listen_socket = Sock}}.
handle_call(_Request, _From, State) ->
Reply = ok,
{reply, Reply, State}.
handle_cast(_Msg, State) ->
{noreply, State}.
handle_info(accept_connection, #state{listen_socket = Sock} = State) ->
{ok, _Pid} = tcp_socket:accept_connection(Sock),
{noreply, State};
handle_info(accept_failed, State) ->
%% If this process knows by some other means that this happened
%% because the application is being shutdown, it can terminate
%% with {stop, normal, State} which will suppress a crash report.
{stop, accept_failed, State};
handle_info(_Info, State) ->
{noreply, State}.
terminate(_Reason, _State) ->
ok.
code_change(_OldVsn, State, _Extra) ->
{ok, State}.
%%%===================================================================
%%% Internal functions
%%%===================================================================
-module(tcp_socket).
-behaviour(gen_server).
%% API
-export([accept_connection/1]).
%% gen_server callbacks
-export([init/1, handle_call/3, handle_cast/2, handle_info/2,
terminate/2, code_change/3]).
-define(SERVER, ?MODULE).
-record(state, {listener_pid, listen_socket, socket}).
%%%===================================================================
%%% API
%%%===================================================================
accept_connection(Listen_socket) ->
Listener_pid = self(),
gen_server:start_link(?MODULE, [Listener_pid, Listen_socket], []).
%%%===================================================================
%%% gen_server callbacks
%%%===================================================================
init([Listener_pid, Listen_socket]) ->
self() ! do_accept,
{ok, #state{listener_pid = Listener_pid, listen_socket = Listen_socket}}.
handle_call(_Request, _From, State) ->
Reply = ok,
{reply, Reply, State}.
handle_cast(_Msg, State) ->
{noreply, State}.
handle_info(do_accept, #state{listener_pid = Listener_pid,
listen_socket = Listen_socket} = State) ->
case gen_tcp:accept(Listen_socket) of
{ok, Socket} ->
Listener_pid ! accept_connection,
inet:setopts(Socket, [{active, once}]),
{noreply, State#state{socket = Socket}};
_Err ->
Listener_pid ! accept_failed,
{stop, normal, State}
end;
handle_info(_Info, State) ->
{noreply, State}.
terminate(_Reason, _State) ->
ok.
code_change(_OldVsn, State, _Extra) ->
{ok, State}.
%%%===================================================================
%%% Internal functions
%%%===================================================================
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment