[erlang-questions] should be a parallel tcp server, but can't connect to more than 1 client

Joe Armstrong erlang@REDACTED
Mon Jan 21 10:54:42 CET 2008


What might have happened here is that the process owning the listening
socket has died.
Sockets are owned by the process that creates the socket. if the
owning process dies the
socket is closed.

If you evaluate start() in the shell then the owning process is the
shell command interpreter,
which usually does not die. If you evaluate start() in some other
process then it might have died in which case
the listening socket will be closed.

If you change accept_con to print an error you should see this:

accept_conn(LSock) ->
     case gen_tcp:accept(LSock) of
         {ok, Sock} ->
            spawn(fun() -> accept_conn(LSock) end),
             handle_conn(Sock);
        X ->
               io:format("OOps:pn", [X])
            true
   end.

The way I'd write accept_con (the way in the Erlang book) is like this:

accept_conn(LSock) ->
     {ok, Sock} = case gen_tcp:accept(LSock),
     spawn(fun() -> accept_conn(LSock) end),
     handle_conn(Sock).

The way you write things is to silently swallow up the error return
with no warnings, which make things difficult
to debug since you get no indication of error. The Erlang way is to
crash hard and early.

If the process owning the listen socket has died then you need to make
sure it lives
forever. I'd add a sleep(infinity) to the code, like this:

start() ->
    case gen_tcp:listen(6002, [binary, {packet, 0}, {active, true},
{reuseaddr, true}]) of
        {ok, Sock} ->
            spawn(fun() -> accept_conn(Sock) end), sleep(infinity);
        {error, Reason} -> {error, Reason}
    end.

where

sleep(T) -> receive after T -> void end.


This version of start can be happily spawned - in the original version
you must ensure that the process evaluating
start() does not die.

Hope this helps

/Joe Armstrong



2008/1/21 Rapsey <rapsey@REDACTED>:
> All this program does is listen on a socket, spawn a new process on every
> connection and send a never ending stream of numbers to each client that
> connects to it. The problem is that once 1 client is connected, no one else
> can connect, even though a new acceptor process has been spawned.
>
>
> start() ->
>     case gen_tcp:listen(6002, [binary, {packet, 0}, {active, true},
> {reuseaddr, true}]) of
>         {ok, Sock} ->
>             spawn(fun() -> accept_conn(Sock) end);
>         {error, Reason} -> {error, Reason}
>     end.
>
>
> accept_conn(LSock) ->
>     case gen_tcp:accept(LSock) of
>         {ok, Sock} ->
>             spawn(fun() -> accept_conn(LSock) end),
>             handle_conn(Sock);
>         _ ->
>             true
>     end.
>
> % wait for http request from browser
> handle_conn(Sock) ->
>     receive
>         {tcp, RecSock, Data} ->
>             send_stream(RecSock, 0);
>         {tcp_closed, _} ->
>             true
>     end.
>
> send_stream(Sock, N) when N == 0 ->
>     gen_tcp:send(Sock, "HTTP/1.1 200 OK\r\nContent-type:
> text/html\r\n\r\n<html><head></head><body>WOHOO<br>"),
>     send_stream(Sock, N + 1);
> send_stream(Sock, N) ->
>     case gen_tcp:send(Sock, integer_to_list(N)) of
>         ok ->
>             timer:sleep(1000),
>             send_stream(Sock, N + 1);
>         Any ->
>             true
>     end.
>
>
> thank you,
> Sergej
>
> _______________________________________________
> erlang-questions mailing list
> erlang-questions@REDACTED
> http://www.erlang.org/mailman/listinfo/erlang-questions
>



More information about the erlang-questions mailing list