Problem detecting interrupted TCP Connection

Mitja Thomas mitja.thomas1@REDACTED
Wed Feb 2 13:08:52 CET 2011


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