How to check if a client has closed a socket.

Hey everyone,

I’ve got a problem in which if a client calls socket.close(), the server never receives an Exception. The server will only receive an Exception if the client actually quits out – as in System.exit(0).

I’ve also done socket.shutdownInput() & socket.shutdownOutput() on the client end, but to no avail.

On the server end, I’m still able to write to the OutputStream without getting any sort of Exception. Why would an Exception not be thrown if I’m writing to an OutputStream that is supposedly closed at the other end? Any thoughts?

Hmm. Ive never seen that. But generally the only palce im worrying about conditions like that are on the read side in order to respond to sudden loss of communication when the sender dies.

Why don’t you send a “Im closing” packet in your own protocol before you close? That seems cleaner and likely to react faster anyway then hoping for an eventual exception. Really the exception should only be used in critical cases, like the sudden death of the partner. Its bad form to use expcetions for expected flow control.

If this is what I think it is, I’ve mentioned this many times before, and it’s in my NIO articles: NIO’s broken w.r.t. throwing ClosedChannelException and it’s ilk :P.

4 years after release, NIO still doesn’t do this properly, off the top of my head (*). A year ago they fixed the worse situation where it almost NEVER threw the CCE - nowadays, it throws it MOST of the time (I had to rewrite the code in my articles to keep up with the bugfixing from sun :)).

(*) - i.e. this is IIRC from looking at the alerts in the instrumented GrexEngine server logs, which record when workaround code paths in the networking are being taken, so that I could spot when Sun finally fixed low-level bugs in it. So…YMMV, I’m not 100% sure of this :).

PS: of course, java 1.0 - 1.3 was far worse: there were situations where you could never detect that a client had disconnected no matter what you did, and you could even get threads that you couldn’t kill cleanly on the server without guessing, and then being brutal.

[quote]Hey everyone,

I’ve got a problem in which if a client calls socket.close(), the server never receives an Exception. The server will only receive an Exception if the client actually quits out – as in System.exit(0).
[/quote]
Sorry, forgot to add: workaround is to look very carefully at numeric return codes on the different function calls. You can “guess” (hey, it’s undocumented! Thanks, Sun: forget to throw the closed exception, AND don’t document how you detect it manually :P) that -1 return codes equate to client connection closed (and, it turns out, you’d be correct ;)) if you knew that the old IO used -1 significantly like that.

You might have to do a read, but IIRC you can catch it on write too, if you inspect carefully enough.

I believe they have documented the returning -1 business now:

http://java.sun.com/j2se/1.4.2/docs/api/java/nio/channels/SocketChannel.html#read(java.nio.ByteBuffer)


Returns:
    The number of bytes read, possibly zero, or -1 if the channel has reached end-of-stream

Thanks for the heads-up, I wasn’t handling this in my app but I will now.

Will.