http://qs321.pair.com?node_id=566568

crenz has asked for the wisdom of the Perl Monks concerning the following question:

Fellow monks,

after a socket connection has been established, is it possible to check whether the socket is still connected without trying to read from or write to the socket? I have tried getpeername, but that (contrary to the docs) returns the peer name even when the socket connection has been interrupted.

I want to use this to find out whether the other application I'm talking to via a socket has crashed.

Replies are listed 'Best First'.
Re: How to find out whether socket is still connected?
by BrowserUk (Patriarch) on Aug 10, 2006 at 09:18 UTC

    If you think about this, there isn't any way you could do this. Let's say you had an established connection, you've written some, you've read some back, and you arrive at the point in your code where you want to make your determination.

    If, at exactly that point, the machine at the other end of the connection dies; or the process holding the socket at that end is killed; or if a power failure takes out a critical router somewhere between your machine and that other machine; there is no way for you to know until you attempt some communication with the other end.

    If the process at the other end takes some deliberate action to sever the connection, close the socket or shutting it down, then the transport layer can send notice of that to your machine, but until you read that notice, whether by attempting to read data, or by querying the status from the transport layer, your code will not know about it.

    You could check for eof each time before you read or write, but as that will only detect deliberate disconnects, your read and write code will still need to check return codes for all the other possible causes of failure anyway, so you might as well skip the attempt and handle the deliberate case in that same code.


    Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
    Lingua non convalesco, consenesco et abolesco. -- Rule 1 has a caveat! -- Who broke the cabal?
    "Science is about questioning the status quo. Questioning authority".
    In the absence of evidence, opinion is indistinguishable from prejudice.
Re: How to find out whether socket is still connected?
by izut (Chaplain) on Aug 10, 2006 at 08:45 UTC

    I think you will know if a socket crashed only when writing to it, and checking this operation results.

    Is the program using some specific protocol, or you are developing your own? IRC, for example, has a PING command for checking connection status.

    If you are responsible for both sides, you can implement something like that.

    Igor 'izut' Sutton
    your code, your rules.

Re: How to find out whether socket is still connected?
by Zaxo (Archbishop) on Aug 10, 2006 at 08:47 UTC

    eof might work. Whether your socket is non-blocking and whether select works on your system is likely to be important.

    After Compline,
    Zaxo

Re: How to find out whether socket is still connected?
by sgifford (Prior) on Aug 10, 2006 at 15:47 UTC
    There are two different situations here. The first is that your peer has gone away and the connection is shut down; either your system has received a TCP RST or FIN packet, or it tried to send data and didn't receive an ACK in time. In that case, Zaxo's suggestion to use select or eof will probably work.

    The other situation is that your peer has disappeared, for example crashed, had a network failure, etc. In this case, there's no way to know that without sending some data. That's why many protocols have a NOOP operation or PING and PONG packets, as izut suggests. TCP keepalives are one option; on many systems you can set a system-wide timeout for TCP connections. If the connections are idle for that long, the kernel will send an empty packet to test the connection, and the connection will be shut down if it receives no response. Unfortunately I don't know of a way to send a 0-size probe packet from userspace.

Re: How to find out whether socket is still connected?
by spadacciniweb (Curate) on Aug 10, 2006 at 09:53 UTC
    In Unix systems, you can try
    system 'netstat -na'
    and you get information about internet connections
    and sockets.

    Update: you can try module Net::Netstat::Wrapper
      lsof -Pni :80
      will also do the trick. Of course substituting your port number for 80.

      Ted
      --
      "That which we persist in doing becomes easier, not that the task itself has become easier, but that our ability to perform it has improved."
        --Ralph Waldo Emerson
Re: How to find out whether socket is still connected?
by kabeldag (Hermit) on Aug 10, 2006 at 13:34 UTC


    With sockets. You have to actually try to touch the other entity (the other process) be it write or read.
    Probably best a write so that you actually ask it to reply. If it doesn't reply then it is not talking correctly.

    If you are unable to read within a period of time, then you can base your control flow on that also.

    Sockets are the Application layer, which is of course above the transport layer (TCP or UDP or whatever).

    You can go an OSI layer lower to the transport layer and work with/look at the packets,
    other wise if the socket (IP:port) can not be reached, I don't think you can say it is open for connections.

    With the pre-packaged modules for sockets in Perl, you try to read from a handle, if you cannot read from it or write to it, then the other entity/process must not be responding for whatever reason.

    Looking at the transport packets to check the state is the way to go.
Re: How to find out whether socket is still connected?
by jesuashok (Curate) on Aug 10, 2006 at 07:59 UTC
    Hi crenz

    In the general case, there's no way of checking whether a socket is connected without actually writing to or reading from it.

    "Keep pouring your ideas"
Re: How to find out whether socket is still connected?
by merlyn (Sage) on Aug 10, 2006 at 15:03 UTC
Re: How to find out whether socket is still connected?
by artax (Acolyte) on Aug 11, 2006 at 13:41 UTC
    I want to use this to find out whether the other application I'm talking to via a socket has crashed.

    You can use the tcp keepalive feature of tcp/ip.

    You must setup a reasonable period of check ( the default is too high ).
    Inside your application you check for the incoming data using the function select().
    When the line on the other end is dropped you will receive an input from the select, but the message read is empty.
    to setup the tcp_keepalive_time you must
    LINUX change the value in /proc/sys/net/ipv4/tcp_keepalive_time

    # echo 60 > /proc/sys/net/ipv4/tcp_keepalive_time

    WINDOWS modify a value in the registry
    HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters "KeepAliveTime"=dword:0000ea61

    You should also enable the keepalive and linger option using the setsockopt function. I give you an example in C. The function setsockopt is also available in perl.
             int ierr;
             bool optval = true;
             ierr = setsockopt( Socket->SocketHandle,
                                     SOL_SOCKET,
                                     SO_KEEPALIVE,
                                     (const char FAR * ) &optval,
                                     sizeof(bool));
             if( ierr == 0 )
             {
                 linger struct_linger;
                 struct_linger.l_onoff  = 1;
                 struct_linger.l_linger = 0;
                 ierr = setsockopt( Socket->SocketHandle,
                                         SOL_SOCKET,
                                         SO_LINGER,
                                         (const char FAR * ) &struct_linger,
                                         sizeof(linger));
    
    

    I hope this info should help
    regards, Enzo
Re: How to find out whether socket is still connected?
by ikegami (Patriarch) on Aug 16, 2006 at 04:03 UTC
    Out of curiosity, which docs? The docs for getpeername don't say anything about indicating whether the socket is still connected or not.
      I confirm getpeername will do the trick. if the remote end has closed connection then getpeername will fail. RS.

        I understand this is an outdated post, but I need confirmation that getpeername is a reliable test that socket is still connected. Is there a best practice please?

Re: How to find out whether socket is still connected?
by djp (Hermit) on Aug 16, 2006 at 03:32 UTC
    A write of zero bytes will do the trick, I believe.