This post is like a bottle tossed to the sea, because everybody here seems to choose RMI against
sockets ...
Anyway, Max writes in
his book (p. 290) :
As of spring 2002, most versions of the SCJD exam explicitly require that either sockets or RMI be used as the networking protocol in your project implementation. This is a firm requirement, meaning that thos adventurous souls who decide to deviate from this requirement may fail automatically upon submission. For this reason, we suggest that you do not use SocketChannels unless your exam instructions state clearly that a SocketChannel implementation is permitted.
That statement, put together with other parts of his book where it appears that NIO may be used for file IO (confirmed by many posts on this forum) may be summed up in this
java pseudocode :
(fileIO == fileNIO) ? feelFreeToChoose() : assert(false)
(networkIO == networkNIO) ? assert(false) : (networkIOChoosen() ? passed() : failed())
I don't see how to justify it. Are SocketChannels really forbidden ? What do you think ?
The reason behind that question is this : Following Max's advice, I used plain sockets and I have nearly finished with it. As I wanted to ensure some scalability (a minimum !) to my network framework, I implemented a client connections queue ("dormant" connections) allocated to threads taken out of a pool of threads. I see two main advantages to that design :
handlers reuse (the threads in the pool) : starting a new thread consumes a lot of CPU cyclesconnections persistency : Any "State" or "session" information may be encapsulated within the ClientConnection - no need for a cookie or other sort of client identification -, and as the server "knows" its clients, it can talk to them : an example of this could be broadcasting a message and a funny (but user-friendly) example of this example could be a smooth port number change
). A ConnectionHandler thread dequeues a ClientConnection (or waits till notified if the queue is empty), and processes the ClientConnection if needed. I'll come back to this "if needed" in a moment. If no network IOException of some sort occurs while processing the ClientConnection (or if there was nothing to process), it's simply reenqueued. Else it is not, meaning that the client will get a SocketException of some sort, forcing it to come back "by the main door" if it decides so.
Now the "... and processes the ClientConnection if needed". Giving that reads on plain sockets are blocking and that ConnectionHandler threads cannot spend time having nothing to do with a given connection, I set client connections SO_TIMEOUT to its mimnimm value (1) and ConnectionHandlers stop reading when they get a SocketTimeoutException. If offset in the buffer read is still 0, there is nothing to process, else the object sent by the client is built from the bytes received. Warning to anybody who would be tempted by this design : you may get a SocketTimeoutException in the middle of the read !! (my tests show that) in which case you get an EOFException in ObjectInputStream.readObject() : the issue is easy to circumvent but you must be aware of it.
But now that everything works fine, I find it so poor in comparison with real multiplexing (SocketChannels). It leads me to think of this car metaphor :
You are shown two cars : a Volkswagen (Socket) and a Ferrari (SocketChannel). You are told that you must choose the Volkswagen. So you "choose" it, but as you like speed cars, you do a hard work on the Volkwagen engine to speed it up, knowing that it will still be far slower despite your efforts. And you know that in the real world (you are a very rich guy
) you wouldn't have hesitate between them at all. What would you do in my place ?
Keep it as it is (1) or refactor and use SocketChannels (2) ? And if you think (1), do you see some hidden issues out there that I didn't take into account ?
Thank you in advance,
Best,
Phil.
[ September 01, 2003: Message edited by: Philippe Maquet ]