Socket / ServerSocket & Remote Disconnection Detecting

Discussion in 'Java' started by Jason Teagle, Oct 2, 2003.

  1. Jason Teagle

    Jason Teagle Guest

    If a client Socket makes a connection to a ServerSocket, and then
    disconnects from it, how can code from the ServerSocket side detect that
    disconnection?

    Similarly, if the ServerSocket closed down the client's connection, how can
    code from the client side detect that disconnection?

    I had some code that was failing, so I generated a new crude test
    application. In the server side, I call isClosed() on the server socket
    every 10th of a second, to see if it is still open. Sure enough, when I
    disconnect the client side deliberately, the server side continues to claim
    that it is connected.

    Just in case it was my code that was naff even in the test app, I used
    breakpoints to make sure it was getting to the check and never to the
    disconnect detection.

    --
    Jason Teagle



    The demo is reproduced below, if anyone is interested (click "Start server",
    then "Connect client", then "Disconnect client" - the console should say "It
    was closed." if it detects the disconnection):


    import java.io.IOException;
    import java.net.ServerSocket;
    import java.util.Timer;
    import java.util.TimerTask;

    /**
    * @author Jason Teagle
    *
    *
    */
    public class JServerSocket extends ServerSocket
    {
    private Timer m_timer ;
    private TimerTask m_task ;

    public JServerSocket(int portNumber) throws IOException
    {
    super(portNumber, 5);

    try
    {
    m_task = new TimerTask()
    {
    public void run()
    {
    checkStatus();
    }
    };
    m_timer = new Timer();
    m_timer.schedule(m_task, 100, 100);
    }
    catch(Exception e)
    {
    System.out.println("Couldn't create server socket.");
    }
    }

    private void checkStatus()
    {
    if (isClosed() )
    System.out.println("It was closed.");
    }

    }



    -----------------------------------------------------------



    import java.net.InetSocketAddress;
    import java.net.Socket;
    import java.net.SocketAddress;

    /**
    * @author Jason Teagle
    *
    *
    */
    public class JClientSocket extends Socket
    {
    public JClientSocket(int portNumber)
    {
    super();

    SocketAddress addr ;

    addr = new InetSocketAddress("127.0.0.1", portNumber);
    try
    {
    connect(addr, 1000);
    }
    catch(Exception e)
    {
    System.out.println("Failed to connect.");
    }
    }

    public void disconnect()
    {
    try
    {
    close();
    }
    catch(Exception e)
    {
    }
    }

    }




    -----------------------------------------------------------



    import java.awt.Container;
    import java.awt.GridLayout;
    import java.awt.event.ActionEvent;
    import java.awt.event.ActionListener;
    import java.awt.event.WindowAdapter;
    import java.awt.event.WindowEvent;

    import javax.swing.JButton;
    import javax.swing.JFrame;

    /**
    * @author Jason Teagle
    *
    *
    */
    public class JMainFrame extends JFrame
    {
    public static void main(String[] args)
    {
    JMainFrame mainFrame = new JMainFrame();
    mainFrame.setVisible(true);
    mainFrame.pack();
    }

    private JServerSocket m_server ;
    private JClientSocket m_client ;

    public JMainFrame()
    {
    super("TestSocketDisconnect");

    Container contentPane ;
    JButton button ;

    m_server = null ;
    m_client = null ;

    contentPane = getContentPane();
    contentPane.setLayout(new GridLayout(3, 1) );

    button = new JButton("Start server");
    button.addActionListener(new ActionListener()
    {
    public void actionPerformed(ActionEvent e)
    {
    startServer();
    }
    }
    );
    contentPane.add(button);

    button = new JButton("Connect client");
    button.addActionListener(new ActionListener()
    {
    public void actionPerformed(ActionEvent e)
    {
    connectClient();
    }
    }
    );
    contentPane.add(button);

    button = new JButton("Dicsonnect client");
    button.addActionListener(new ActionListener()
    {
    public void actionPerformed(ActionEvent e)
    {
    disconnectClient();
    }
    }
    );
    contentPane.add(button);

    addWindowListener(new WindowAdapter()
    {
    public void windowClosing(WindowEvent e)
    {
    System.exit(0);
    }
    }
    );
    }

    private void startServer()
    {
    if (m_server == null)
    {
    try
    {
    m_server = new JServerSocket(1234);
    }
    catch(Exception e)
    {
    System.out.println("Unable to construct server socket.");
    }
    }
    }

    private void connectClient()
    {
    if (m_client == null)
    m_client = new JClientSocket(1234);
    }

    private void disconnectClient()
    {
    if (m_client != null)
    {
    m_client.disconnect();
    m_client = null ;
    }
    }

    }
     
    Jason Teagle, Oct 2, 2003
    #1
    1. Advertising

  2. Jason Teagle

    Jason Teagle Guest

    > The demo is reproduced below, if anyone is interested (click "Start
    server",
    > then "Connect client", then "Disconnect client" - the console should say

    "It
    > was closed." if it detects the disconnection):


    OK, that was a little embarrassing - the code for the server socket was not
    even calling accept(), which is a bit silly of me. In my defence, the actual
    code of mine that was failing was the client end, so it DID call isClosed()
    and did NOT need to accept anything {:v)

    But even when I do call accept() correctly as I should, and call
    isConnected() rather than isClosed(), it still NEVER detects the
    disconnection.

    Help?

    Here's the corrected code for the server socket:

    import java.io.IOException;
    import java.net.ServerSocket;
    import java.net.Socket;
    import java.util.Timer;
    import java.util.TimerTask;

    /**
    * @author Jason Teagle
    *
    *
    */
    public class JServerSocket extends ServerSocket
    {
    private Socket m_otherSocket ;
    private Timer m_timer ;
    private TimerTask m_task ;

    public JServerSocket(int portNumber) throws IOException
    {
    super(portNumber, 5);

    try
    {
    m_task = new TimerTask()
    {
    public void run()
    {
    checkStatus();
    }
    };
    m_timer = new Timer();
    m_timer.schedule(m_task, 100, 100);
    }
    catch(Exception e)
    {
    System.out.println("Couldn't create server socket.");
    m_otherSocket = null ;
    m_timer = null ;
    m_task = null ;
    }
    }

    private void checkStatus()
    {
    if (m_otherSocket == null)
    {
    try
    {
    // First time we hit here, we actually start listening. This
    // won't allow the timer thread to continue until a client
    // actually connects, THEN it starts checking the connection
    // status (confirmed by breakpoints).
    m_otherSocket = accept();
    }
    catch(Exception e)
    {
    }
    }
    if (m_otherSocket != null && !m_otherSocket.isConnected() )
    {
    // Never gets here.
    System.out.println("It was closed.");
    }
    }

    }
     
    Jason Teagle, Oct 2, 2003
    #2
    1. Advertising

  3. On Thu, 2 Oct 2003 18:08:40 +0100, Jason Teagle wrote:
    > If a client Socket makes a connection to a ServerSocket, and then
    > disconnects from it, how can code from the ServerSocket side detect
    > that disconnection?
    >
    > Similarly, if the ServerSocket closed down the client's connection,
    > how can code from the client side detect that disconnection?


    The ServerSocket is never connected to the (client) Socket.
    ServerSocket.accept() returns a new Socket, i.e. the resulting
    connection is between two Sockets.

    The ServerSocket and resulting Socket are completely distinct and have
    nothing to do with each other's subsequent state, so either one can
    close without affecting the other. More specifically, the ServerSocket
    cannot detect when one of "its" Sockets have closed.

    The only way to check for disconnection is to read from or write to
    the Socket (through one of its streams). This doesn't apply to
    ServerSockets, which are never connected.

    isClosed() can only be used to detect if the corresponding close()
    method has been called. The documentation doesn't define "the closed
    state" but the library source is clear enough.

    /gordon

    --
    [ do not email me copies of your followups ]
    g o r d o n + n e w s @ b a l d e r 1 3 . s e
     
    Gordon Beaton, Oct 2, 2003
    #3
  4. Jason Teagle

    Jason Teagle Guest

    > isClosed() can only be used to detect if the corresponding close()
    > method has been called. The documentation doesn't define "the closed
    > state" but the library source is clear enough.


    What about Socket's isConnected() method (if called on one of the sockets
    that results from accept(), which you'll see I realised about 10 minutes
    later)? That seems to be giving bogus information after the client has
    disconnected from it.


    --
    --
    Jason Teagle
     
    Jason Teagle, Oct 2, 2003
    #4
  5. On Thu, 02 Oct 2003 18:08:40 +0100, Jason Teagle wrote:

    > If a client Socket makes a connection to a ServerSocket, and then
    > disconnects from it, how can code from the ServerSocket side detect that
    > disconnection?


    On the server side, when you call accept() on the ServerSocket, you will
    get a Socket object. You will want to put all reads and writes to the
    Socket object in a try{} block and catch any IOException that is raised.

    If the socket connection has been closed from the client side, you
    will detect the disconnection with the code in the catch(IOException ioe)
    block.

    The ServerSocket object is no longer involved after the accept() and
    all future communication is the responsibility of the Socket object
    on the server side.

    >
    > Similarly, if the ServerSocket closed down the client's connection, how can
    > code from the client side detect that disconnection?


    Similiar to above, put all reads and writes to the Socket in a try block
    and catch(IOException ioe) code will be invoked when the socket connection
    is disconnected from the server side.

    Sajjad
     
    Sajjad Lateef, Oct 2, 2003
    #5
  6. On Thu, 2 Oct 2003 18:46:12 +0100, Jason Teagle wrote:
    > What about Socket's isConnected() method


    It just tells you whether the Socket has been connected at some time.
    In other words, it tells you that that the Socket was created in the
    connected state or that connect() has been successfully called. It
    says nothing about the actual state of the Socket.

    Although the method's API documentation could be much clearer, it does
    say "true if the socket successfully connected to a server", not "is
    connected to a server". The source code verifies what is meant.

    Once again, the only way to determine whether the Socket really is
    connected is to read from or write to it.

    /gordon

    --
    [ do not email me copies of your followups ]
    g o r d o n + n e w s @ b a l d e r 1 3 . s e
     
    Gordon Beaton, Oct 2, 2003
    #6
  7. "Jason Teagle" <> wrote in message
    news:blhm2q$cgkb2$-berlin.de...
    > If a client Socket makes a connection to a ServerSocket, and then
    > disconnects from it, how can code from the ServerSocket side detect that
    > disconnection?
    >
    > Similarly, if the ServerSocket closed down the client's connection, how

    can
    > code from the client side detect that disconnection?
    >
    > I had some code that was failing, so I generated a new crude test
    > application. In the server side, I call isClosed() on the server socket
    > every 10th of a second, to see if it is still open. Sure enough, when I
    > disconnect the client side deliberately, the server side continues to

    claim
    > that it is connected.
    >
    > Just in case it was my code that was naff even in the test app, I used
    > breakpoints to make sure it was getting to the check and never to the
    > disconnect detection.
    >
    > --
    > Jason Teagle
    >
    >



    <snip>

    I presume that you mean the socket on the server side that is connected (via
    an accept() on the ServerSocket) to the client socket.

    Unless there is an attempt to read or write, it is not possible under TCP to
    detect a broken or closed connection.

    In other words, a broken or closed connection looks the same as a quiet
    connection.

    Typically, if one has control over the protocol, one can arrange to have
    some periodic traffic (some read and write activity) over the virtual
    circuit so that an Exception may be generated when trying to communicate.

    Some network cards can detect if the other end has been disconnected, and
    depending upon your OS and drivers, this is conveyed up to the TCP stack
    (and therefore the Java socket) via an exception. This is not universal,
    but can be used in some applications where the situation is well-controlled.

    HTH,


    --
    Shripathi Kamath
    NETAPHOR SOFTWARE INC.
    http://www.netaphor.com
     
    Shripathi Kamath, Oct 2, 2003
    #7
  8. Jason Teagle

    Roedy Green Guest

    On Thu, 2 Oct 2003 18:08:40 +0100, "Jason Teagle"
    <> wrote or quoted :

    > the server side continues to claim
    >that it is connected.


    Quiet sockets don't send packets back and forth do they, even with
    keepalive?

    You can send heartbeat packets back and forth at the application level
    that let you know the connection is still alive. This is what I have
    done without problem.


    --
    Canadian Mind Products, Roedy Green.
    Coaching, problem solving, economical contract programming.
    See http://mindprod.com/jgloss/jgloss.html for The Java Glossary.
    try http://24.87.56.253 if you have trouble getting through.
     
    Roedy Green, Oct 2, 2003
    #8
  9. Jason Teagle

    Jason Teagle Guest

    > You can send heartbeat packets back and forth at the application level
    > that let you know the connection is still alive. This is what I have
    > done without problem.


    This only works if you control the server and client sides, and thus can
    arrange for such packets to pass back and forth harmlessly. If you're
    working with a server using an established protocol such as FTP or HTTP,
    this isn't feasible since the server would attempt to parse whatever you
    send and you don't want that erroneous data. Waiting until you have
    something genuine to send may be too late to find out. Imagine if you're
    listening for incoming data from a (read-only) device that is sending
    periodic data to you - if it goes silent, is that because it just doesn't
    have any more data to send right now or because the connection was lost?

    There MUST be a way to test it (maybe not in Java), otherwise Visual C++'s
    CAsyncSocket wouldn't be able to tell you the connection had dropped, and I
    know Delphi can do it also (I've tried to find info on this by Googling, and
    caught some similar articles).

    I hate Java's "just try to use it and see if it breaks" attitude (grumble,
    grumble) {:v)


    --
    --
    Jason Teagle
     
    Jason Teagle, Oct 3, 2003
    #9
  10. Jason Teagle

    EJP Guest

    Read with a timeout or use Selector.select(). There is no other way in
    Java because there is no other way in TCP/IP.

    Jason Teagle wrote:
    >
    > > You can send heartbeat packets back and forth at the application level
    > > that let you know the connection is still alive. This is what I have
    > > done without problem.

    >
    > This only works if you control the server and client sides, and thus can
    > arrange for such packets to pass back and forth harmlessly. If you're
    > working with a server using an established protocol such as FTP or HTTP,
    > this isn't feasible since the server would attempt to parse whatever you
    > send and you don't want that erroneous data. Waiting until you have
    > something genuine to send may be too late to find out. Imagine if you're
    > listening for incoming data from a (read-only) device that is sending
    > periodic data to you - if it goes silent, is that because it just doesn't
    > have any more data to send right now or because the connection was lost?
    >
    > There MUST be a way to test it (maybe not in Java), otherwise Visual C++'s
    > CAsyncSocket wouldn't be able to tell you the connection had dropped, and I
    > know Delphi can do it also (I've tried to find info on this by Googling, and
    > caught some similar articles).
    >
    > I hate Java's "just try to use it and see if it breaks" attitude (grumble,
    > grumble) {:v)
    >
    > --
    > --
    > Jason Teagle
    >
     
    EJP, Oct 4, 2003
    #10
  11. Jason Teagle

    Jason Teagle Guest

    "EJP" <> wrote in message
    news:...

    > Read with a timeout or


    No good as a test. If the connection is live and data is available, it will
    read the data available. This is thus not a test, it's an actual read (I
    refer you back to my rambling speech about finding out during an actual read
    / write being too late).

    >use Selector.select().


    This looks interesting - I might play around with this.

    >because there is no other way in TCP/IP.


    If the mighty MS can do it with their CAsyncSocket, I'm sure Java can do it,
    if they tried. Surely Sun don't want to be outdone by the alleged root of
    all evil? {:v)


    --
    --
    Jason Teagle
     
    Jason Teagle, Oct 4, 2003
    #11
  12. Jason Teagle

    EJP Guest

    MS do it with select(). There are no other ways.

    Jason Teagle wrote:
    >
    > "EJP" <> wrote in message
    > news:...
    >
    > > Read with a timeout or

    >
    > No good as a test. If the connection is live and data is available, it will
    > read the data available. This is thus not a test, it's an actual read (I
    > refer you back to my rambling speech about finding out during an actual read
    > / write being too late).
    >
    > >use Selector.select().

    >
    > This looks interesting - I might play around with this.
    >
    > >because there is no other way in TCP/IP.

    >
    > If the mighty MS can do it with their CAsyncSocket, I'm sure Java can do it,
    > if they tried. Surely Sun don't want to be outdone by the alleged root of
    > all evil? {:v)
    >
    > --
    > --
    > Jason Teagle
    >
     
    EJP, Oct 5, 2003
    #12
  13. Jason Teagle

    Jason Teagle Guest

    "EJP" <> wrote in message
    news:...

    > MS do it with select(). There are no other ways.


    OK, I'll see what I can do with that, thanks.


    --
    --
    Jason Teagle
     
    Jason Teagle, Oct 5, 2003
    #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. Avizz
    Replies:
    3
    Views:
    13,827
    Andy Fish
    Sep 29, 2003
  2. DennyOR
    Replies:
    10
    Views:
    1,151
    Chris Uppal
    May 13, 2005
  3. oziris
    Replies:
    5
    Views:
    2,728
  4. JPractitioner
    Replies:
    3
    Views:
    381
    JPractitioner
    Feb 16, 2006
  5. Iñaki Baz Castillo
    Replies:
    7
    Views:
    563
    Iñaki Baz Castillo
    Jan 12, 2010
Loading...

Share This Page