[erlang-questions] Issue with my simple server, accept not accepting connections

bbrown bbrown@REDACTED
Fri Mar 7 18:44:24 CET 2008

Hello, this kind of a long post (lot of code) and maybe I need to simplify my
code but I am writing a simple tcp server and maybe you see something that is
totally off.  I have one application module and a server module (a type of
middle-man) and then the client-handler module.

Everything gets called correctly, but I can't connect to the server.  I get a
connection refused for example if 

This is my server library as a gen_server module.

The key code is here and my issue.  When I try to connect to the server, it
looks like it never calls the code after "accept".

I get to this line:
io:format("trace: lib:handle_call accept_clients. [~p]~n", [AppHandler])

But I don't get to this line after the accept call:

	io:format("trace: [!!] lib:handle_call client-socket: [~p]~n", [ClientSock]),


	io:format("trace: lib:handle_call accept_clients. [~p]~n", [AppHandler]),
	ClientSock = server_accept(ServSock),
	io:format("trace: [!!] lib:handle_call client-socket: [~p]~n", [ClientSock]),


server_accept(ServSock) ->	
	{ ok, ClientSock } = gen_tcp:accept(ServSock),
handle_call(irc_server_bind, _From,
			#server_state{client=Client } = State) ->
	Port = Client#irc_server_info.port,
	io:format("trace: lib:handle_call:bind Port:<~p>~n", [Port]),
    {ok, ServSock} = server_bind(Port),
    {reply, ok, State#server_state{serv_sock=ServSock, state=connecting}};
handle_call(irc_accept_clients, _From,
			#server_state{serv_sock=ServSock, app_handler=AppHandler } = State) ->	
	io:format("trace: lib:handle_call accept_clients. [~p]~n", [AppHandler]),
	ClientSock = server_accept(ServSock),
	io:format("trace: [!!] lib:handle_call client-socket: [~p]~n", [ClientSock]),
	{ ok, ClientServ } = client_handler:start_link(),
	% Assign a new controlling process.
	gen_tcp:controlling_process(ClientSock, ClientServ),
	inet:setopts(ClientSock, [{packet, 0}, binary, 
							  {nodelay, true},{active, false}]),	
	% Invoke gen_server:cast to handle the socket	
	{reply, ok, State};
handle_call(get_cur_state, _From, #server_state{} = State) ->
	% Generic method to get the current state.
	io:format("trace: lib:handle_call:get_cur_state~n"),
	{reply, {ok, State}, State}.

terminate(_Reason, #server_state{client=Client}) ->
    io:format("trace: lib:terminate reason:[~p]~n", [_Reason]),
terminate(shutdown, #server_state{client=Client}) ->
    io:format("trace: lib:terminate.shutdown~n"),

handle_info(server_timeout, #server_state{client=Client} = State) ->
	io:format("trace: lib:handle_info.server_timeout"),
    %{noreply, State#server_state{state=timeout, connection_timeout=undefined}}.
	{noreply, State}.

server_listen(ServLib) ->  
	io:format("trace: lib:server listen [~p]~n", [ServLib]),
	% Synchronous gen_server call
	gen_server:call(ServLib, irc_server_bind).

%% Accept call and then cast to handle new client
server_accept_call(ServLib) ->
	io:format("trace: lib:server accept new client~n"),
	gen_server:call(ServLib, irc_accept_clients).

get_cur_state(ServLib) ->
	io:format("trace: lib:get_cur_state: pid:[~p] ~n", [ServLib]),
	% Return: {ok, State}
	gen_server:call(ServLib, get_cur_state).

server_bind(Port) ->
	io:format("trace: attempting to bind server... [~p]~n", [Port]),
	gen_tcp:listen(Port, [binary, {packet, 0}, 
						  {active, false}]).

server_accept(ServSock) ->	
	{ ok, ClientSock } = gen_tcp:accept(ServSock),

connection_timeout() ->
    % Time out delay of 1 minute

start_test_serv() ->
	io:format("Running functional test~n"),
	% Ensure that the app_handler is associcated with this app process
	Client = #irc_server_info{app_handler=self()},
	Pid = start(Client),
	io:format("trace: <after start> start server, handler:~p ~n", [Pid]),
	% Wait a couple of seconds and then send messages to wait_for_clients.
	% Pass the pid of the server handler process.

wait_for_clients(ServHandler) ->
	io:format("trace: app: wait_for_clients~n"),
        Anything ->
			% Application process is ready to accept new clients
            io:format("trace: app: wait_messages:accept <incoming>~n"),
    after connection_timeout() + 20000 ->
            io:format("INFO: Timed out~n")

Here is my server handler code.

server_handler(Client) ->
	ServStart = server_lib:start_link(Client),
	case ServStart of
		{ ok, P } ->
			io:format("trace: app:server pid/lib [~p]~n", [P]),
			State = server_lib:get_cur_state(P),
			% io:format("trace: app:server state [~p]~n", [State]),
			server_handler(#serv_handler_info{lib_handler=P}, idle)

server_handler(ServClient, idle) ->
	ServLib = ServClient#serv_handler_info.lib_handler,
	io:format("trace: [!] at server_handler.idle [~p]~n", [ServLib]),
		{ ready_accept } ->
		    % Application process is ready to accept new clients			
			io:format("trace: app: wait_messages:accept <incoming>~n"),
			% Launch initial accept clients block
			AcceptCall = server_lib:server_accept_call(ServLib),
			io:format("!!!-->~p~n", [AcceptCall]),
			case AcceptCall of
				{ ok, State } ->
			server_handler(ServClient, idle);
		Error ->
			io:format("trace: [!] app:error.proceeed<idle>: ~p~n", [Error]),
			server_handler(ServClient, idle)
    after connection_timeout() ->
            io:format("trace: [!] at server_handler. TIMEOUT ~n"),
            server_handler(ServClient, idle)

accept_clients(ServHandler) ->
	% Start waiting accept new client connections.
    ServHandler ! {ready_accept}.

init_accept_clients() ->
	% Start waiting accept new client connections.
    self() ! {init_accept}.


And if you are really curious; here is the source in subversion:


Berlin Brown
email: berlin-dot-brown-AT-gmail-dot-com

More information about the erlang-questions mailing list