tags:

views:

75

answers:

1

I've made a tcp server witch spawns a process to listen incoming connections. Here is the sample code (removed a few things from my original code):

module a:

main([]) ->
    { ok, Pid } = b:start(),
    receive
            _ ->
                    ok
    end.

module b:

-define(TCP_OPTIONS, [binary, { active, false}, { packet, 0 } , {reuseaddr, true}]).

...

start_link(Port) ->
    Pid = spawn_link(server_listener, init, [ Port ]),
    { ok , self() }.

init(Port, Processor) ->
    case gen_tcp:listen(Port, ?TCP_OPTIONS) of
     { ok , LSocket } ->
           accept_loop(LSocket);
     { error, Reason } ->
        { stop, Reason }
     end.

accept_loop( LSocket) ->
  ?LOG("Current socket acceptor PID [~w]~n", [self()]),
  case gen_tcp:accept(LSocket) of
      { ok, Socket } ->   
      %do stuff here
         spawn(server_listener , accept_loop, [ LSocket ]);
      { error, Reason }  ->
         ?LOG("Error accepting socket! [ ~s ]~n", [ Reason ])   
  end.

The problem is: EVERY time that I try to connect from telnet on this port, I'm receiving an error { error, closed } on gen_tcp:accept. This is already driving me nuts trying to figure out what is happening.

Thanks,

+2  A: 

Your "accept loop" isn't really a loop... and it is contrived.

You probably want "do_accept_loop" and a proper "server_loop" for handling a connection. Have a look at this.

You want something along the lines of:

% Call echo:listen(Port) to start the service.
listen(Port) ->
    {ok, LSocket} = gen_tcp:listen(Port, ?TCP_OPTIONS),
    accept(LSocket).

% Wait for incoming connections and spawn the echo loop when we get one.
accept(LSocket) ->
    {ok, Socket} = gen_tcp:accept(LSocket),
    spawn(fun() -> loop(Socket) end),
    accept(LSocket).

% Echo back whatever data we receive on Socket.
loop(Socket) ->
    case gen_tcp:recv(Socket, 0) of
        {ok, Data} ->
            gen_tcp:send(Socket, Data),
            loop(Socket);
        {error, closed} ->
            ok
    end.
jldupont
@scooterman: I have provided a link in my answer. In your `init` function, you call `accept_loop` but what you should be doing is calling a function that spawns a server for this connection. That's why I suggested something along the lines of `do_accept`.Furthermore, you need a proper `loop` function for your spawned server. Your `accept_loop` isn't *looping* at all. Have a look at the link I provided.
jldupont
Lol you were faster than me. Looking at your example, I've changed the "spawn(server_listener , accept_loop, [ LSocket ]);" (just after %do stuff here) for "accept_loop(LSocket)" and it worked! So I'm figuring that the spawn call was slower than my current process exit, making my accept socket close before the new one started.Thanks anyway!
scooterman