nio OP_WRITE

P

patrick

Im trying to understand java.nio but am a bit confused.
Below is code for a server from Java in a Nutshell.

What i dont understand is when OP_WRITE should be registered with a
channel.??
Or when key.isWritable is needed before sending data to a client??

Below client is registered only for OP_READ with:
SelectionKey clientkey =
client.register(selector,
SelectionKey.OP_READ);

Yet later in the code data is sent from server to client in these lines:
// Wrap, encode, and write the response string
client.write(encoder.encode(CharBuffer.
wrap(response)));

Does the client channel's key not need to be isWritable before sending data
to the client??



any help appreciated.
p butler



Java in a Nutshell code:
----------------------------
SelectionKey serverkey = server.register(selector,
SelectionKey.OP_ACCEPT);

for(;;) { // The main server loop. The server runs forever.
// This call blocks until there is activity on one of the
// registered channels. This is the key method in nonblocking
// I/O.
selector.select();

// Get a java.util.Set containing the SelectionKey objects for
// all channels that are ready for I/O.
Set keys = selector.selectedKeys();

// Use a java.util.Iterator to loop through the selected keys
for(Iterator i = keys.iterator(); i.hasNext(); ) {
// Get the next SelectionKey in the set, and remove it
// from the set. It must be removed explicitly, or it will
// be returned again by the next call to select().
SelectionKey key = (SelectionKey) i.next();
i.remove();

// Check whether this key is the SelectionKey obtained when
// you registered the ServerSocketChannel.
if (key == serverkey) {
// Activity on the ServerSocketChannel means a client
// is trying to connect to the server.
if (key.isAcceptable()) {
// Accept the client connection and obtain a
// SocketChannel to communicate with the client.
SocketChannel client = server.accept();
// Put the client channel in nonblocking mode
client.configureBlocking(false);
// Now register it with the Selector object,
// telling it that you'd like to know when
// there is data to be read from this channel.
SelectionKey clientkey =
client.register(selector,
SelectionKey.OP_READ);
// Attach some client state to the key. You'll
// use this state when you talk to the client.
clientkey.attach(new Integer(0));
}
}
else {
// If the key obtained from the Set of keys is not the
// ServerSocketChannel key, then it must be a key
// representing one of the client connections.
// Get the channel from the key.
SocketChannel client = (SocketChannel) key.channel();

// If you are here, there should be data to read from
// the channel, but double-check.
if (!key.isReadable()) continue;

// Now read bytes from the client. Assume that all the
// client's bytes are in one read operation.
int bytesread = client.read(buffer);

// If read() returns -1, it indicates end-of-stream,
// which means the client has disconnected, so
// deregister the selection key and close the channel.
if (bytesread == -1) {
key.cancel();
client.close();
continue;
}

// Otherwise, decode the bytes to a request string
buffer.flip();
String request = decoder.decode(buffer).toString();
buffer.clear();
// Now reply to the client based on the request string
if (request.trim().equals("quit")) {
// If the request was "quit", send a final message
// Close the channel and deregister the
// SelectionKey
client.write(encoder.encode(CharBuffer.
wrap("Bye.")));
key.cancel();
client.close();
}
else {
// Otherwise, send a response string comprised of
// the sequence number of this request plus an
// uppercase version of the request string. Note
// that you keep track of the sequence number by
// "attaching" an Integer object to the
// SelectionKey and incrementing it each time.

// Get sequence number from SelectionKey
int num = ((Integer)key.attachment()).intValue();
// For response string

String response = num + ": " +
request.toUpperCase();
// Wrap, encode, and write the response string
client.write(encoder.encode(CharBuffer.
wrap(response)));
// Attach an incremented sequence nubmer to the key
key.attach(new Integer(num+1));
}
}
}
}
}
}
 
C

Cyrille \cns\ Szymanski

What i dont understand is when OP_WRITE should be registered with a
channel.??

You almost never need to register a channel with OP_WRITE because usually
you don't matter when your data has been sent. Keep in mind that a
channel spends most of its time writable so this test isn't very
interesting.

Or when key.isWritable is needed before sending data to a client??

No, you only call key.isWritable when you have registered the channel
with OP_WRITE. If the write() method fails, an exception is raised.

Below client is registered only for OP_READ with:
SelectionKey clientkey =
client.register(selector,
SelectionKey.OP_READ);

Yet later in the code data is sent from server to client in these
lines:
// Wrap, encode, and write the response string
client.write(encoder.encode(CharBuffer.
wrap(response)));

Does the client channel's key not need to be isWritable before sending
data to the client??

Should the write fail, an exception would be raised. If everything goes
well, data is queued in the socket's output buffer.


Acceptance informs you of incoming connections
Readability informs you that data has arrived : it is ready for the
server to process.

For a server application the only two Ops of interest are OP_ACCEPT and
OP_READ.
For a client application those are OP_CONNECT and OP_READ.
 

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

Members online

Forum statistics

Threads
473,769
Messages
2,569,582
Members
45,065
Latest member
OrderGreenAcreCBD

Latest Threads

Top