[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