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));
}
}
}
}
}
}
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));
}
}
}
}
}
}