[erlang-questions] Problem detecting interrupted TCP Connection

Ladislav Lenart lenartlad@REDACTED
Wed Feb 2 14:20:34 CET 2011


I might be wrong, but I think that opening a socket in the active mode
introduces a race condition: the socket can deliver TCP messages to the
acceptor process instead of the loop process even before the call to set
a new controlling process.

As a general recommendation from discussions on this list I'd say that
the socket should be opened in {active, false} mode, then the control
should be transferred to the appropriate process which should set mode
to {active, once} whenever it is ready to handle another TCP message
and thus implement a form of flow control.

Please correct me if this is not so.


Ladislav Lenart

Joe Armstrong wrote:
> I tried your code and it worked beautifully - but I had to remove the
> {ip, {xxx,...}} term - if you omit the IP then you this will default to the
> local interface
> then you can do
>    > telnet localhost 8999, or
>    > telnet 8999, or
>    > telnet <My eth0 IPv4 address> 8999
> all worked as expected
> /Joe
> On Wed, Feb 2, 2011 at 1:08 PM, Mitja Thomas <mitja.thomas1@REDACTED>wrote:
>> Hello Folks,
>> I'm new to this Mailing List, so my question might already have been
>> answered at some point. Still I got a strange behaviour in a TCP Session
>> which I just cant figur out.
>> Beckground:
>> I have a Server who listens on a Port for incomming TCP Connections and
>> handles them in a User List. When something happens for this User (on the
>> other side, which doesnt matter for the problem), the user is informed and
>> can send commands. When the TCP Connection ist closed, the Socket is closed
>> and the User will be erased from the User list.
>> Problem:
>> When the user somehow disconnects his TCP/IP Connection and closes the
>> client application, my server dont get the tcp_closed Event and the user is
>> still present in the List. Well I know this is the way TCP should behave,
>> thus the server tries to send a packet to the Socket once in while and
>> should receive and Error of some kind. But it does not, it just keeps
>> "sending", without actually sending TCP Packets.
>> The Problem is well explained in gen_tcp manual page and an example how it
>> should be handled in such a way with an application ping is given. But I
>> just dont the {error, timeout} while trying to send to the broken TCP
>> Socket.
>> I broke it down to a simple Server, who just pings the client and tried
>> various ways to do it. Im pretty sure, Im doing something wrong, but I just
>> dont know what. Any Help is appreciated.
>> Regards
>> Mitja
>> sample Code (Client is normally a simple Telnet):
>> -module(tcp).
>> -compile(export_all).
>> start() ->
>>    {ok, Listener} = gen_tcp:listen(8999, [binary, {ip, {xxx,xxx,xxx,xxx}},
>> {active, true}, {packet, 0}, {keepalive, true}, {reuseaddr, true},
>> {send_timeout_close, true}, {send_timeout, 100}]),
>>    io:format("Listener started~n"),
>>    acceptor(Listener).
>> acceptor(Listener) ->
>>        case gen_tcp:accept(Listener, 1000) of
>>        {ok, Socket} ->
>>                io:format("Starting client (~p)\n", [Socket]),
>>            Pid=spawn_link(fun()->loop(Socket) end),
>>                gen_tcp:controlling_process(Socket, Pid),
>>            acceptor(Listener);
>>        {error, timeout} -> io:format("still running\n"),
>> acceptor(Listener);
>>        X -> io:format("SocketError:~p~n", [X])
>>    end.
>> loop(Socket) ->
>>    receive
>>        {tcp, Socket, Data} ->
>>            io:format("Client: Received '~p'\n", [Data]),
>>            loop(Socket);
>>        {tcp_closed, Socket} ->
>>            % This is the desired close Event
>>            io:format("Client: Socket closed by remote\n");
>>        {tcp_error, Socket, Reason} ->
>>            io:format("Client: Socket error '~p'\n", [Reason])
>>    after
>>        1000 ->
>>            case gen_tcp:send(Socket, "Ping\r\n") of
>>                                Ret ->
>>                                        % If Ping fails the output should be
>> =/= ok
>>                                        io:format("Send ret value:~p~n",
>> [Ret]),
>>                                        loop(Socket)
>>                        end
>>    end.

More information about the erlang-questions mailing list