I just wrote a long and detailed response to this. Unfortunately, Mozilla bitch-slapped me (stupid moronic key shortcuts handling, and whilst I was trying to fix what it just did to me it crashed before I could hit "Post") and I haven't the time left to rewrite the whole thing.
So, in brief:
- part of the problem is that the tutorial code is actually wrong. Trust me, I wrote it
- this is Sun's fault, not mine. They have NOT documented what "actually happens" nor "how you should use this". As a result, I had to use trial-and-error to work out many of the details. Their JVM was broken (1.4.1 and also the first 1.4.2 IIRC) and I accidentally coded these tutorials to work with the BROKEN behaviour of specific versions of Sun's JVM. Because they didn't document this, I didn't find out until some aspects of our production code stopped working when we tried upgrading the JVM.
- ...but it didn't hit us hard, because the real code that I used as a basis for the tutorial has a LOT more defensive programming in it, most of which I stripped out for the tutorial to make it clearer and easier to read. None of it was "essential".
- However, until now I completely forgot that the tutorial would need updating too!
1. In the block where you deal with the "undocumented feature" which is still in the latest Sun JVM (and you HAVE to support even though it's undocumented), I have a better approach now. Instead of the code in the tutorial, just use the line:
throw new ClosedChannelException();
2. ...because Sun has fixed their JVM, which used to NEVER throw this exception, but now it does. Often. So you have to catch it anyway, and if you're doing that, you might as well use it. However, they haven't quite fixed all their bugs, because there are occasions when you get the -1 read INSTEAD of a ClosedChannelException - but I *believe* from reading between the lines Sun *intended* to throw that exception. Hence my recommendation that you do it yourself.
3. Modify your code to catch those CCException's. It's pretty obvious what causes them - the other end of the connection has disappeared for any of a variety of reasons, so take whatever actions are appropriate in your game when someone disconnects.
I would almost bet money that doing this will catch that IOException you are getting
If you follow the above advice, you'll be deleting the "closeChannel ( ... )" code, but FYI since you asked I just had a pretty boring method that did little more than Channel.close().
The reason I *had* the method is that there have been changes from version-to-version about what happens when you try to close channels - and, again, Sun has failed to adequately document what you ought
to do. So I had that method so I could tweak it each time they changed the JVM behaviour
. Nowadays, I find that just catching the CCExcepiton is enough, and don't normally need to close anything manually.
EDIT: two more things to add.
1. The above advice may be wrong. If a Sun engineer came to this forum and said so I would be overjoyed. For the 3 years or so that NIO has been around, I have never seen or heard of any human who claims to know how NIO works (and I've scoured the web many times looking for all the info I could find anywhere on NIO). I think Sun decided they "knew too much" and executed them as soon as they'd finished their work, just like Pharoahs and their pyramid-builders.
I'd be even happier if he/she also explained WHY and gave us some documentation for this API!
2. I haven't bothered reading the 1.5.x API docs yet - I'm waiting until 1.5 goes gold (at the moment it's still beta and subject to change). It could be that there are wonderful detailed API docs for NIO that explain all this.
If so, my apologies for misleading you. However, there are several servers on the net at the moment using my NIO libraries that have been serving games for months at a time without restarting the JVM, so you can rest assured I actually use this stuff in real life
. Unlike Ron Hitchens (author of the ONLY NIO book) whose book is a nice introduction to NIO, but makes it look like he's never used the API himself!