GeeCON Prague 2014*
The moose likes Sockets and Internet Protocols and the fly likes Detecting client disconnection events Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login


JavaRanch » Java Forums » Java » Sockets and Internet Protocols
Bookmark "Detecting client disconnection events" Watch "Detecting client disconnection events" New topic
Author

Detecting client disconnection events

Chandramouli Ram
Ranch Hand

Joined: Mar 07, 2005
Posts: 65
I am using java.nio for a client-server application.
The issue is with detecting connection closure by clients.

I started by server program in Eclipse and client program in a DOS command window.

Scenario 1: If I run the server as well as the client on the same machine, here is what I observe:

If the client closes the connection
a) by programmatically closing its Input/Output stream with the Server
OR
b) by typing Ctrl-C in a DOS command window,

the number of bytes read, as returned by socketChannel.read(buffer) is -1.
This facilitates an easy cleanup once the client disconnects.

If the client aborts the connection say by closing the DOS command window,
it results in an IOException to be thrown by the Server program:

java.io.IOException: An existing connection was forcibly closed by the remote host
at sun.nio.ch.SocketDispatcher.read0(Native Method)
at sun.nio.ch.SocketDispatcher.read(Unknown Source)
at sun.nio.ch.IOUtil.readIntoNativeBuffer(Unknown Source)
at sun.nio.ch.IOUtil.read(Unknown Source)
at sun.nio.ch.SocketChannelImpl.read(Unknown Source)...

=====================================================================

Scenario 2: If I repeat the same steps with the server and the client running on different machines:

Programmatic closing of the streams by client (Exception at the Server end):

java.io.IOException: An established connection was aborted by the software in your host machine
at sun.nio.ch.SocketDispatcher.read0(Native Method)
at sun.nio.ch.SocketDispatcher.read(Unknown Source)
at sun.nio.ch.IOUtil.readIntoNativeBuffer(Unknown Source)
at sun.nio.ch.IOUtil.read(Unknown Source)
at sun.nio.ch.SocketChannelImpl.read(Unknown Source)


Typing Ctrl-C in a DOS command window running on client machine (Exception at the Server end):

java.io.IOException: An existing connection was forcibly closed by the remote host
at sun.nio.ch.SocketDispatcher.read0(Native Method)
at sun.nio.ch.SocketDispatcher.read(Unknown Source)
at sun.nio.ch.IOUtil.readIntoNativeBuffer(Unknown Source)
at sun.nio.ch.IOUtil.read(Unknown Source)
at sun.nio.ch.SocketChannelImpl.read(Unknown Source)

Closing the command (DOS) window, the client uses for communicating (Exception at the Server end):

java.io.IOException: An existing connection was forcibly closed by the remote host
at sun.nio.ch.SocketDispatcher.read0(Native Method)
at sun.nio.ch.SocketDispatcher.read(Unknown Source)
at sun.nio.ch.IOUtil.readIntoNativeBuffer(Unknown Source)
at sun.nio.ch.IOUtil.read(Unknown Source)
at sun.nio.ch.SocketChannelImpl.read(Unknown Source)

Is there any other elegant way to trap these events?


Thanks & Regards,<br />Chandramouli Ram
Stan James
(instanceof Sidekick)
Ranch Hand

Joined: Jan 29, 2003
Posts: 8791
What a fascinating variety of messages! Good work on trying so many different scenarios.

Are you looking to do more than just catch IOException and abandon that client? The server can't reconnect or anything useful, can it?


A good question is never answered. It is not a bolt to be tightened into place but a seed to be planted and to bear more seed toward the hope of greening the landscape of the idea. John Ciardi
Chandramouli Ram
Ranch Hand

Joined: Mar 07, 2005
Posts: 65
Thanks for your response Stan.
You have a very valid question!


Are you looking to do more than just catch IOException and abandon that client? The server can't reconnect or anything useful, can it?

========================================================================
A little more background:
I have a processor that may take while to process the client request and may be running in a different thread and sending "heart-beat" messages to the client till the processing is completed. On completion of the process, a response is sent to the client.

Task on client disconnection:
If I detect client disconnection, I just need to inform the processor to abandon the processing of this request. Additionally, I log the Socket & port that got closed (which is not possible if an IOException is thrown -unless I store these info upfront, when the client connects), cancel the respective SelectionKey, close the SocketChannel etc.

The real issue:
If I only get an IOException with a variety of messages, how do I programmatically figure out what happened? Doing a String comaprison of the actual message, may not work with any change in JDK version and is also considered to be a bad practice- Effective Java by Joshua Bloch (Chapter 8)!
Any suggestion would help.

Thanks again,
Ram Chandramouli
Stan James
(instanceof Sidekick)
Ranch Hand

Joined: Jan 29, 2003
Posts: 8791
I'd take any IOException - or probably any other - as a sign that things have gone bad. Do you imagine taking different actions based on the different messages?
Chandramouli Ram
Ranch Hand

Joined: Mar 07, 2005
Posts: 65
I want to do the tasks that I mentioned above, on client disconnection. If it's anything else, I don't need to do anything specific at this point.
So, if I need to do something specific based on the exception message, is there an established strategy?
Dave Michels
Greenhorn

Joined: Mar 29, 2007
Posts: 5
It sounds like what you're trying to do would constitute deriving your own
protocol
for the exchanges between your client's and server.

If you think of it like a JDBC connection. You don't manage/interact with the underlying TCP connection as the drivers do so for you and negotiate the vendor specific protocol so things like
login
and
disconnect
are handled (Hence, why it's so important to call the close() of the java.sql.Connection when the process is finished using it). In order to manage these different
events
that can occur through the connection, you will likely need define something of a message protocol (if you haven't already) that denotes the type of message being sent over the connection. That way on the client side, when the client exits or disconnects, you can send the appropriate message to the server indicating that you want it to terminate any thread associated with that client (i.e. clean up any server side resources).

Hope that helps a little...
Chandramouli Ram
Ranch Hand

Joined: Mar 07, 2005
Posts: 65
Thank you Dave for your thoughtful input.
At this point, I need to write only the server side logic. Also, based on the exception messages, it's clear that the information I need is actually captured by java.io and the issue is how to extract it in an elegant way, if any.
For my immediate requirement, I am using the actual exception message, and may need to work out an alternative subsequently.
 
GeeCON Prague 2014
 
subject: Detecting client disconnection events