• Post Reply Bookmark Topic Watch Topic
  • New Topic
programming forums Java Mobile Certification Databases Caching Books Engineering Micro Controllers OS Languages Paradigms IDEs Build Tools Frameworks Application Servers Open Source This Site Careers Other Pie Elite all forums
this forum made possible by our volunteer staff, including ...
Marshals:
  • Campbell Ritchie
  • Tim Cooke
  • Liutauras Vilda
  • Jeanne Boyarsky
  • paul wheaton
Sheriffs:
  • Ron McLeod
  • Devaka Cooray
  • Henry Wong
Saloon Keepers:
  • Tim Holloway
  • Stephan van Hulst
  • Carey Brown
  • Tim Moores
  • Mikalai Zaikin
Bartenders:
  • Frits Walraven

Detecting client disconnection events

 
Ranch Hand
Posts: 65
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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?
 
(instanceof Sidekick)
Posts: 8791
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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?
 
Chandramouli Ram
Ranch Hand
Posts: 65
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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)
Posts: 8791
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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
Posts: 65
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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?
 
Greenhorn
Posts: 5
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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
Posts: 65
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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.
 
To get a wish, you need a genie. To get a genie, you need a lamp. To get a lamp, you need a tiny ad:
Gift giving made easy with the permaculture playing cards
https://coderanch.com/t/777758/Gift-giving-easy-permaculture-playing
reply
    Bookmark Topic Watch Topic
  • New Topic