NIO - OP_READ fired on client disconnect

F

farseer

I have a server that listens for connections. A selector is opened,
configured for non-blocking and the serverchannel is used to register
OP_ACCEPT on this selector. in the main loop, once i accept a
connection, i immediately register OP_READ on the selector.
So far so good...A connection request is made by a client, i accept, i
register to read; when the client sends data, i read the data and send
back an ACK. All good!

Now, i created a client which simply connects to the server, sends a
message and recieves back an acknowledgement from the server. about
100 to 500 client threads are created for testing. They all work
flawlessly, almost. the server accepts each connection, process the
data each thread sends and then when it's done with all connections,
blocks on select() it appears.

THE PROBLEM IS: when i now kill the client process (the one with 100
to 500 threads), the server immediately wakes up and tries to process a
READ_OP event. I currently handle this by closing/canceling the key
and channel if an IOException is detected in the method that reads, but
i am wondering why does the Server wake up when clients abruptly
disconnects?
I also noticed the converse happens..if the server is killed, the
client tries to process a OP_READ event.

Anyone with some thoughts?
 
E

Esmond Pitt

farseer said:
I have a server that listens for connections. A selector is opened,
configured for non-blocking and the serverchannel is used to register
OP_ACCEPT on this selector. in the main loop, once i accept a
connection, i immediately register OP_READ on the selector.
So far so good...A connection request is made by a client, i accept, i
register to read; when the client sends data, i read the data and send
back an ACK. All good!

Now, i created a client which simply connects to the server, sends a
message and recieves back an acknowledgement from the server. about
100 to 500 client threads are created for testing. They all work
flawlessly, almost. the server accepts each connection, process the
data each thread sends and then when it's done with all connections,
blocks on select() it appears.

THE PROBLEM IS: when i now kill the client process (the one with 100
to 500 threads), the server immediately wakes up and tries to process a
READ_OP event. I currently handle this by closing/canceling the key
and channel if an IOException is detected in the method that reads, but
i am wondering why does the Server wake up when clients abruptly
disconnects?
I also noticed the converse happens..if the server is killed, the
client tries to process a OP_READ event.

Anyone with some thoughts?

OP_READ is fired if either data or an EOF is available or the connection
has been reset.
 
F

farseer

ok, thanks and that would explain it.

Question, when a READ is fired and i retrieve the key, is there away to
prevent that from firing again, but still keep the channel open for
sending?
The problem i am having now is that when i read, i add an object to a
synchronized "queue". I have a number of threads then blocking on that
queue when it's empty...so that when something is added, one of the
threads picks it up and processes it.

However, i find that the same key is added a number of times to that
queue because the read is constantly fired until i do a read from that
channel's socket. so basically, if a thread is a bit slow to pick an
object from the queue that was just added, that object may be added
more than once.
I can fix this by ensureing the items in the queue is unique, but that
seems like a lame fix, since it still means processing time.
 
E

Esmond Pitt

farseer said:
Question, when a READ is fired and i retrieve the key, is there away to
prevent that from firing again, but still keep the channel open for
sending?
The problem i am having now is that when i read, i add an object to a
synchronized "queue". I have a number of threads then blocking on that
queue when it's empty...so that when something is added, one of the
threads picks it up and processes it.

However, i find that the same key is added a number of times to that
queue because the read is constantly fired until i do a read from that
channel's socket. so basically, if a thread is a bit slow to pick an
object from the queue that was just added, that object may be added
more than once.

Eh??? This can only happen if you can somehow manage to read the object
from the socket more than once, which you can't, or unless you have a
bug in your code, which is at least possible.
 
F

farseer

the confusion is from me. when i say "read", i should have said when i
PROCESS THE READ EVENT. at that point i am not actually reading form
the buffer, but adding the the object to a queue for processing. the
threads actually do the reading...but, at times, before the actually
complete reading, the event could fire again.
 
E

Esmond Pitt

farseer said:
the confusion is from me. when i say "read", i should have said when i
PROCESS THE READ EVENT. at that point i am not actually reading form
the buffer, but adding the the object to a queue for processing. the
threads actually do the reading...but, at times, before the actually
complete reading, the event could fire again.

then surely you just have to defer adding the object to a queue until
the read completes? ...

also why the baroque architecture? the read won't block, why not do it
in the same thread?
 
F

farseer

i think i solved it...by removing the OP_READ event after i recieve
that event, and adding it back after i finish reading prevents the
events for that channel from being fired.

to answer your questions:
-first question - well, it's kind of the chicken and egg problem. The
threads block on an empty queue. when there is something in the queue,
the awake and process it. so i have to add something to the queue each
time an event is fired.
-yes, you're right, i should read in the same thread since it doesnt'
block....but i still would need to to "turn off" OP_READ when
processing buffer, since that is done in a different thread and i don't
want that buffer being updated while i am reading.
 
E

Esmond Pitt

farseer said:
i think i solved it...by removing the OP_READ event after i recieve
that event, and adding it back after i finish reading prevents the
events for that channel from being fired.

to answer your questions:
-first question - well, it's kind of the chicken and egg problem. The
threads block on an empty queue. when there is something in the queue,
the awake and process it. so i have to add something to the queue each
time an event is fired.
-yes, you're right, i should read in the same thread since it doesnt'
block....but i still would need to to "turn off" OP_READ when
processing buffer, since that is done in a different thread and i don't
want that buffer being updated while i am reading.

I have been thinking about this and you have hit on the correct
solution. You were treating OP_READ as a discrete event corresponding
precisely to a client request, and it just isn't.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Similar Threads

NIO 12
Socket disconnect on client end 6
NIO writing to a channel 6
nio OP_WRITE 3
need a nio client app 4
NIO vs Threads 1
NIO on sun doesnot give WRITE notification 4
Java NIO disconnects unnoticed? 1

Members online

No members online now.

Forum statistics

Threads
473,756
Messages
2,569,535
Members
45,008
Latest member
obedient dusk

Latest Threads

Top