Sockets - Checking For Dropped Connections & close()

Discussion in 'Java' started by JTeagle, Oct 3, 2007.

  1. JTeagle

    JTeagle Guest

    What is the correct way to determine if a socket to which you were
    connected has been closed, either by implicitly calling close() on it,
    or because the code that created it has been terminated?

    This, for example, does not do what I believe it should:

    import java.net.InetAddress;
    import java.net.ServerSocket;
    import java.net.Socket;

    import javax.swing.JOptionPane;

    public class TestSocketCloseApp
    {
    public static void main(String[] args)
    {
    try
    {
    // Create a listening socket.
    ServerSocket listener = new ServerSocket(9999);

    // Create a client socket and initiate a connection.
    Socket client = new
    Socket(InetAddress.getLocalHost().getHostAddress(), 9999);
    // Stop it from lingering - when we say close, we mean close.
    client.setSoLinger(false, 0);

    // Accept a connection from this client socket.
    Socket server = listener.accept();

    // Now close the client connection.
    client.close();

    // What does the server say our state is?
    if (server.isConnected() )
    JOptionPane.showMessageDialog(null,"Apparently we're still
    connected.");
    else
    JOptionPane.showMessageDialog(null,"As expected, we're
    disconnected.");

    server.close();
    listener.close();
    }
    catch(Exception e)
    {
    }
    }

    }


    It still thinks it's connected when I clearly closed the other end.

    I have tried other options in my original code - grabbing the output
    stream and sending data (that didn't fail, even though there should be
    no link), trying to request the remote address we are connected to -
    they all work as if we are still connected.

    Does close() not do what it claims? I would say it's fairly
    fundamental of any program that deals with socket connections to know
    when the other end has dropped.
     
    JTeagle, Oct 3, 2007
    #1
    1. Advertising

  2. On Wed, 03 Oct 2007 00:56:35 -0700, JTeagle wrote:
    > What is the correct way to determine if a socket to which you were
    > connected has been closed, either by implicitly calling close() on
    > it, or because the code that created it has been terminated?


    When isConnected() is true, it only indicates that s.connect() has
    been called at some previous time. It says nothing about the state of
    the underlying socket itself.

    To determine whether the socket has been closed, attempt to read()
    from it or write() to it. Either of these operations will indicate EOF
    (exactly how depends on which class you use to read or write).

    /gordon

    --
     
    Gordon Beaton, Oct 3, 2007
    #2
    1. Advertising

  3. On Wed, 03 Oct 2007 00:56:35 -0700, JTeagle wrote:
    > What is the correct way to determine if a socket to which you were
    > connected has been closed, either by implicitly calling close() on it,
    > or because the code that created it has been terminated?


    I find it interesting that you asked the exact same question exactly 4
    years (plus one day) ago. It was answered then, but you seem to be
    making the same mistakes again.

    /gordon

    --
     
    Gordon Beaton, Oct 3, 2007
    #3
  4. JTeagle

    JTeagle Guest

    On Oct 3, 9:50 am, Gordon Beaton <> wrote:
    > On Wed, 03 Oct 2007 00:56:35 -0700, JTeagle wrote:
    > > What is the correct way to determine if a socket to which you were
    > > connected has been closed, either by implicitly calling close() on it,
    > > or because the code that created it has been terminated?

    >
    > I find it interesting that you asked the exact same question exactly 4
    > years (plus one day) ago. It was answered then, but you seem to be
    > making the same mistakes again.
    >
    > /gordon
    >
    > --


    I guess that means the API is still badly named - if there were
    functions that actually did what they claim in the name, we wouldn't
    be here again.

    Not sure how you found that previous message - even I hadn't
    remembered that - it's been that long since I did any Java. Pity the
    API hasn't improved much since then.

    The problem with doing a read is that if the socket hasn't closed, you
    end up blocking - it defeats the purpose of a 'test' to see if the
    socket is closed. The problem with a write is that you end up writing
    spurious data out to the socket. If the implementation can tell (when
    you read or write) that the network has been lost, why can't it do so
    to provide a proper test method - hasRemoteSocketClosed(), for
    example?

    Sorry that I brought the same question back.
     
    JTeagle, Oct 3, 2007
    #4
  5. On Wed, 03 Oct 2007 12:08:38 -0000, JTeagle wrote:
    > I guess that means the API is still badly named - if there were
    > functions that actually did what they claim in the name, we wouldn't
    > be here again.


    The methods are poorly named, but they do work as documented.

    > Not sure how you found that previous message - even I hadn't
    > remembered that - it's been that long since I did any Java. Pity the
    > API hasn't improved much since then.


    I recognized the question, and the asker...

    > The problem with doing a read is that if the socket hasn't closed, you
    > end up blocking - it defeats the purpose of a 'test' to see if the
    > socket is closed. The problem with a write is that you end up writing
    > spurious data out to the socket. If the implementation can tell (when
    > you read or write) that the network has been lost, why can't it do so
    > to provide a proper test method - hasRemoteSocketClosed(), for
    > example?


    The socket interface provided by the OS works that way, and in that
    respect there is no difference reading from any kind of descriptor,
    regardless of the underlying structure (file, pipe, socket, character
    device, etc). Not all of these interact with a remote that actively
    closes the other end.

    Note too that the remote may have closed while you have remaining
    unread data, in which case you don't actually reach EOF until you've
    read to the end of the data stream.

    If you don't want to risk blocking, use a Selector. It provides the
    necessary test, and will tell you when you can safely read *without*
    blocking.

    /gordon

    --
     
    Gordon Beaton, Oct 3, 2007
    #5
  6. JTeagle

    JTeagle Guest

    > The methods are poorly named, but they do work as documented.

    The docs are a bit lacking in that respect - they need to make the
    distinction between "is currently connected" and "has connected at
    some moment in the past" clear for new programmers, but I accept your
    point.

    > I recognized the question, and the asker...


    I guess I should worry about that in my spare time! {:v)

    > Note too that the remote may have closed while you have remaining
    > unread data, in which case you don't actually reach EOF until you've
    > read to the end of the data stream.


    That's a very valid point. My initial problem was that available() on
    the BufferedInputStream() returns 0 even when disconnected, which is
    fairly logical but not helpful - this prompted me to look more
    closely.

    > If you don't want to risk blocking, use a Selector. It provides the
    > necessary test, and will tell you when you can safely read *without*
    > blocking.


    Unfortunately that doesn't help - I'm assuming that's similar to
    available(), which as mentioned above returns 0 for the disconnected
    case (technically, there are 0 bytes you can read from a closed socket
    without blocking), which doesn't hint that the connection has been
    lost.

    I did eventually realise, however, that I can use setSoTimeout() on
    the socket to minimise blocking time.

    Thanks for your thoughts.
     
    JTeagle, Oct 3, 2007
    #6
  7. On Wed, 03 Oct 2007 12:39:29 -0000, JTeagle wrote:
    >> If you don't want to risk blocking, use a Selector. It provides the
    >> necessary test, and will tell you when you can safely read *without*
    >> blocking.

    >
    > Unfortunately that doesn't help - I'm assuming that's similar to
    > available(), which as mentioned above returns 0 for the disconnected
    > case (technically, there are 0 bytes you can read from a closed
    > socket without blocking), which doesn't hint that the connection has
    > been lost.


    A Selector can tell you when it's safe to read without blocking.
    Actually reading is still necessary to tell you whether there was data
    to read, or you're at EOF. A single Selector can be used to monitor
    many existing and arriving connections simultaneously for connecting,
    accepting, reading or writing, according to which SelectionKeys you've
    registered interest in.

    InputStream.available() tells you how much data has arrived and is
    waiting to be read on a single InputStream. It can't tell the
    difference between EOF and "currently no data", so reading might still
    block.

    /gordon

    --
     
    Gordon Beaton, Oct 3, 2007
    #7
  8. JTeagle

    JTeagle Guest

    > A Selector can tell you when it's safe to read without blocking.
    > Actually reading is still necessary to tell you whether there was data
    > to read, or you're at EOF. A single Selector can be used to monitor
    > many existing and arriving connections simultaneously for connecting,
    > accepting, reading or writing, according to which SelectionKeys you've
    > registered interest in.
    >
    > InputStream.available() tells you how much data has arrived and is
    > waiting to be read on a single InputStream. It can't tell the
    > difference between EOF and "currently no data", so reading might still
    > block.


    OK... I'll look into trying a Selector. Thanks.
     
    JTeagle, Oct 3, 2007
    #8
  9. JTeagle

    Lew Guest

    JTeagle wrote:
    >> The methods are poorly named, but they do work as documented.

    >
    > The docs are a bit lacking in that respect - they need to make the
    > distinction between "is currently connected" and "has connected at
    > some moment in the past" clear for new programmers, but I accept your
    > point.


    Blame the docs, blame the language, but by no means blame yourself.

    Here's what the docs say:
    > true if the socket successfuly connected to a server


    We look at your code and see that the socket successfully connected to a
    server. Working as advertised. Nothing there says the socket still has to be
    connected. Yep, still working as advertised.

    --
    Lew
     
    Lew, Oct 3, 2007
    #9
  10. Lew wrote:
    > JTeagle wrote:
    >>> The methods are poorly named, but they do work as documented.

    >>
    >> The docs are a bit lacking in that respect - they need to make the
    >> distinction between "is currently connected" and "has connected at
    >> some moment in the past" clear for new programmers, but I accept your
    >> point.

    >
    > Blame the docs


    Rather than blaming the docs, suggest an improvement.


    bool Socket.isConnected()
    Indicates if connect() has been called on this socket.
    Initially this method returns false. After a connection is established,
    this method method returns true. It will never change back to false for
    any reason (like the connection failing).

    bool Socket.isClosed()
    Indicates if close() has been called on this socket.
    Initially this method returns false. After Socket.close() is invoked
    this method returns true. It will not return true for any other reason
    (like the connection being closed by the remote end).
     
    Thomas Schodt, Oct 3, 2007
    #10
  11. JTeagle

    Esmond Pitt Guest

    JTeagle wrote:
    > // Stop it from lingering - when we say close, we mean close.
    > client.setSoLinger(false, 0);


    Don't do this. Don't even think about doing it unless (i) you're
    prepared to lose the last piece of data you wrote, and (ii) you're
    prepared to read data on the next connection that may not belong to you.

    TCP/IP has the TIME-WAIT state for a very good reason. Don't break it.
     
    Esmond Pitt, Oct 9, 2007
    #11
  12. Hi Esmond,

    > and (ii) you're
    > prepared to read data on the next connection that may not belong to you.
    >


    Is there an example of this on the web somewhere? Peculiar to Java?

    Cheers Richard Maher

    "Esmond Pitt" <> wrote in message
    news:ISFOi.7262$...
    > JTeagle wrote:
    > > // Stop it from lingering - when we say close, we mean close.
    > > client.setSoLinger(false, 0);

    >
    > Don't do this. Don't even think about doing it unless (i) you're
    > prepared to lose the last piece of data you wrote, and (ii) you're
    > prepared to read data on the next connection that may not belong to you.
    >
    > TCP/IP has the TIME-WAIT state for a very good reason. Don't break it.
     
    Richard Maher, Oct 9, 2007
    #12
  13. JTeagle

    Esmond Pitt Guest

    Richard Maher wrote:
    > Is there an example of this on the web somewhere? Peculiar to Java?


    Any 'example' would consist of a misbehaving application, not a piece of
    code, and it has nothing to do with Java. It's discussed in the TCP/IP
    RFCs.
     
    Esmond Pitt, Oct 12, 2007
    #13
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Joshua Jung
    Replies:
    5
    Views:
    2,268
    Joshua Jung
    Oct 4, 2006
  2. Joshua Jung

    Dropped Sockets?

    Joshua Jung, Oct 12, 2006, in forum: Java
    Replies:
    5
    Views:
    406
    Tom Forsmo
    Oct 17, 2006
  3. jobs
    Replies:
    2
    Views:
    907
  4. binaryj
    Replies:
    1
    Views:
    510
    Jonathan Gardner
    Mar 24, 2008
  5. Iñaki Baz Castillo
    Replies:
    7
    Views:
    917
    Iñaki Baz Castillo
    Jan 12, 2010
Loading...

Share This Page