Oroboros102
Oroboros102

Reputation: 2254

Communicating between nio OP_READ and OP_WRITE operations

I'm trying to implement java.nio Selector based http server (for fun). On key.isReadable() I'm reading data like this:

ByteBuffer buf = ByteBuffer.allocate(4096);
SocketChannel client = (SocketChannel) key.channel();
//Gathering whole client request
((ByteBufferQueue) key.attachment()).enqueue(buf);
key.interestOps(SelectionKey.OP_READ | SelectionKey.OP_WRITE);

Please, look at gathering client's request. Is it a common practice to collect ByteBuffers in some kind of queues during OP_READ operations? Is there any other (more optimal) way to communicate between OP_READ and OP_WRITE operations?

Upvotes: 1

Views: 869

Answers (1)

user207421
user207421

Reputation: 310884

Allocate a ByteBuffer per accepted channel, and save it as the key attachment, or in a session object that is used as the key attachment, that might contain other things as well.

When OP_READ fires, you should then read. Don't futz around queuing things.

NB OP_WRITE is almost always ready, except when the socket send buffer is full. It is therefore not correct to register it as an interestOp except when the socket buffer is full, which you can detect by write() returning zero. At all other times you should just write when you have something to write. If write() returns zero, then register OP_WRITE (and not OP_READ), and when you get it, retry the write: if it completes, deregister OP_WRITE and register OP_READ. If you have OP_WRITE registered all the time, the selector will never wait, it will just spin.

Upvotes: 5

Related Questions