Re: Java NIO Strategy
<wesley.hall@gmail.com> wrote in message
news:1165581080.871869.280140@f1g2000cwa.googlegroups.com...
Karl Uppiano wrote:
"Wesley Hall" <noreply@example.com> wrote in message
news:4578bfbe$0$8755$ed2619ec@ptn-nntp-reader02.plus.net...
mearvk wrote:
EJP wrote:
The attachment is generally used as a Session object. It can contain
the
SocketChannel state (what state would that be?), information about
the
user, information about the current transaction.
Alternatively you can use the SelectionKey as a key into a
Map<SelectionKey,Session>, but this seems contrived to me compared to
using the key attachment.
I keep track of things like what state the server thinks the client is
in, in a SocketChannelState object. For instance, my clients have a
protocol to login. They cannot perform any meaningful commands until
they have performed the login protocol. So, the best quick solution I
could come up with is to maintain state for each SelectionKey via the
attach() method. At first I thought this might be problematic because
I
was worried that the key's state would also get removed on the
iterator.remove() call, but I have found this technique workable.
However, for multiple logical flows (encryption to different endpoints
for instance) over the same physical flow, I am quickly realising this
requires some heavier-duty stateful objects. The Map is worth
considering as I will ultimately have to build more state into my
program.
Anyways, for all the hurrahs about NIO I am finding it rather
cumbersome. If you have any good strategies for these kinds of issues,
feel free to let me know! :-)
Thanks for your reply,
Mearvk
Mearvk,
You are right, the NIO libraries are not simple to work with, SSL is
especially troublesome.
To solve your problem, you may want to consider creating a 'Session'
object and making your connection state value a field within that
'Session' object. This will allow you to store other required values
within this object.
I keep everything about the client in the attachment, including the
callback
(event listener) to notify the client of incoming data. I don't have to
look
up, or switch or run any conditional logic. I simply execute -- Bam! I
think
NIO is a beautiful thing.
As long as you can handle 'part messages' then this is a nice approach.
The problem with having a heavy 'attachment' on selection keys is that
if the key doesn't wake up, that attachment is held indefinately. You
have no oppurtunity to close the connection and no oppurtunity to kill
the key that is holding on to your attachement. It wont be GCed.
An NIO application that has heavy key attachments and an unreliable
upstream network has the potential to leak memory like a sieve.
Something to be aware of.
My particular application is TELNET terminal applications (TN3270/E, TN5250,
Unisys, VT, etc.). So the "client" is actually a TN decoder. Whenever the
channel receives data, the selector wakes up and calls the attached TELNET
decoder, filling in a buffer with decoded data. When a packet containing a
TELNET EOR (end of record) is received, the buffer is forwarded to the
terminal for further processing and display. When client needs to send data,
we "wake up" the selector to gain access to the selector thread, to encode
the data and send it off (note that we do not use async NIO for transmit -
it does not seem worth the trouble for what we have to send. There is no
significant delay or wait time for the transmit buffer to drain out). Then
it goes back to monitoring connections for received data. If the connection
is closed by the host, the selector wakes up. Or we can wake up the selector
and close it on our end. This is a commercial product in a very high volume
server application, and we have not had any problem with memory or resource
leaks. I cannot remember all of the details of our application at the
moment, but we do have inactivity timeouts to reclaim unresponsive
connections.