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

Berlin Brown berlin.brown@REDACTED
Sat Mar 8 19:00:10 CET 2008


On Sat, Mar 8, 2008 at 10:54 AM, Pablo Polvorin
<pablo.polvorin@REDACTED> wrote:
> Try to establish a tcp connection *really* quickly after starting the
>  server and see what happens..  you will be able to connect (and then
>  crash with {undef,[{client_handler,start_link,[]).
>  I guess the reason you can't connect to the server is that you are
>  hitting a timeout inside your gen_server: handle_call/3
>  implementation (witch doesn't return in the expected time).
>
>  Anyway, there is an introductory  TCP server example <chargen.erl>, at
>  http://www.erlang.org/examples/klacke_examples/index.html
>  you could use that as a starting point for simplifying your code.
>
>  cheers,
>  pablo.
>
>
>
>  2008/3/7, bbrown <bbrown@REDACTED>:
>
>
> > 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),
>  >         ClientSock.
>  >  -----------------
>  >  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]),
>  >     ok;
>  >  terminate(shutdown, #server_state{client=Client}) ->
>  >     io:format("trace: lib:terminate.shutdown~n"),
>  >     ok.
>  >
>  >  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),
>  >         ClientSock.
>  >
>  >  connection_timeout() ->
>  >     % Time out delay of 1 minute
>  >     600000.
>  >  ----------------
>  >
>  >  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.
>  >         timer:sleep(500),
>  >         init_accept_clients(),
>  >         % Pass the pid of the server handler process.
>  >         wait_for_clients(Pid),
>  >         io:format("Done~n").
>  >
>  >  wait_for_clients(ServHandler) ->
>  >         io:format("trace: app: wait_for_clients~n"),
>  >     receive
>  >         Anything ->
>  >                         % Application process is ready to accept new clients
>  >             io:format("trace: app: wait_messages:accept <incoming>~n"),
>  >                         accept_clients(ServHandler),
>  >             wait_for_clients(ServHandler)
>  >     after connection_timeout() + 20000 ->
>  >             io:format("INFO: Timed out~n")
>  >     end.
>  >  -----------------
>  >
>  >  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]),
>  >                         server_lib:server_listen(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)
>  >         end.
>  >
>  >  server_handler(ServClient, idle) ->
>  >         ServLib = ServClient#serv_handler_info.lib_handler,
>  >         io:format("trace: [!] at server_handler.idle [~p]~n", [ServLib]),
>  >         receive
>  >                 { 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 } ->
>  >                                         io:format("poo~n")
>  >                         end,
>  >                         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)
>  >     end.
>  >
>  >  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:
>  >
>  >  http://openbotlist.googlecode.com/svn/trunk/botlistprojects/laughingman/test/ircserver/src/
>  >
>  >  --
>  >  Berlin Brown
>  >  email: berlin-dot-brown-AT-gmail-dot-com
>  >  http://botspiritcompany.com/botlist/
>  >
>  >  _______________________________________________
>  >  erlang-questions mailing list
>  >  erlang-questions@REDACTED
>  >  http://www.erlang.org/mailman/listinfo/erlang-questions
>  >
>
>
>  --
>  --
>  pablo
>  http://ppolv.wordpress.com
>  ----
>  _______________________________________________
>  erlang-questions mailing list
>  erlang-questions@REDACTED
>  http://www.erlang.org/mailman/listinfo/erlang-questions
>

I found the error, it was a copy paste error; I had returned the wrong
type and then in later code, it was expecting a different type and
hence the function_clause error.

I changed this...
{noreply, {noreply, State}};

To what is below...

handle_info({tcp, Sock, Data}, State) ->	
    inet:setopts(Sock, [{active, once}]),
	io:format("trace: lib:info.tcp data [~p]~n", [Data]),
 	% Invoke the client data handler to process incoming messages.
 	HandleState=client_handle_data(State, {Prefix, Command, Args}),
    {noreply, State};


-- 
Berlin Brown
http://botspiritcompany.com/botlist/spring/help/about.html



More information about the erlang-questions mailing list