Hi Everyone,
I have a non blocking server which accepts new connections as per the
acceptConnections() method below.
Connections are closed by calling channel.socket().close();
The server works fine, however after sometime we notice that the CPU
usage becomes 100% even though the server continues to function
normally.
I assume that this is due to the channels not being closed after being
registered for an OP_WRITE. However, I am not sure why that would
occur.
If someone can help it would be great!
Thanks!
Rajat
=======================
public void acceptConnections() throws IOException,
InterruptedException {
SelectionKey acceptKey =
this.selectableChannel.register(this.selector,SelectionKey.OP_ACCEPT);
while ((this.keysAdded = acceptKey.selector().select()) > 0) {
Set readyKeys = this.selector.selectedKeys();
Iterator i = readyKeys.iterator();
while (i.hasNext()) {
try {
SelectionKey key = (SelectionKey) i.next();
i.remove();
if (key.isAcceptable()) {
ServerSocketChannel nextReady = (ServerSocketChannel) key
.channel();
SocketChannel channel = nextReady.accept();
if (db.checkIPBanning(channel.socket().getInetAddress()
.toString())) {
channel.configureBlocking(false);
SelectionKey readKey = channel.register(
this.selector, SelectionKey.OP_READ);
readKey.attach(new ClientConnection(this, channel,
"" + channel.socket().getPort()
+ channel.socket().getInetAddress()
+ ran.nextInt()));
} else {
channel.socket().close();
System.out.println("Banned IP ... "
+ channel.socket().getInetAddress()
.toString());
}
} else if (key.isReadable()) {
try {
this.readMessage((ClientConnection) key
.attachment());
} catch (Exception e) {
key.channel().close();
}
}
} catch (Exception e) {
}
}
}
}
Gordon Beaton - 25 Aug 2006 10:29 GMT
> The server works fine, however after sometime we notice that the CPU
> usage becomes 100% even though the server continues to function
[quoted text clipped - 3 lines]
> being registered for an OP_WRITE. However, I am not sure why that
> would occur.
Why do you assume this? I don't see OP_WRITE mentioned in your code.
> else if (key.isReadable()) {
> try {
[quoted text clipped - 4 lines]
> }
> }
What does readMessage() do when it reaches EOF?
/gordon

Signature
[ don't email me support questions or followups ]
g o r d o n + n e w s @ b a l d e r 1 3 . s e
rajatag - 25 Aug 2006 11:57 GMT
1. I was assuming OP_WRITE because at one point I had set OP_WRITE with
OP_READ and it lead to 100% CPU usage.
2. Here is the code for readMessage(). It is set to call a function
when it encounters end of line. I guess EOF is handled by default?
public void readMessage(ClientConnection callback) throws IOException,
InterruptedException {
ByteBuffer byteBuffer = ByteBuffer.allocate(BUFSIZE);
callback.getChannel().read(byteBuffer);
byteBuffer.flip();
String result = this.decode(byteBuffer);
callback.append(result.toString());
if (result.indexOf("\n") >= 0)
callback.process();
}
Thanks!
Gordon Beaton - 25 Aug 2006 12:20 GMT
> 2. Here is the code for readMessage(). It is set to call a function
> when it encounters end of line. I guess EOF is handled by default?
[quoted text clipped - 9 lines]
> callback.process();
> }
If a client crashes or simply closes the socket, Channel.read() will
reach EOF and return -1, and no exception will be raised.
You should *always* check the return value from read().
If you fail to close the channel after reaching EOF, the channel will
remain readable and the selector loop will spin.
/gordon

Signature
[ don't email me support questions or followups ]
g o r d o n + n e w s @ b a l d e r 1 3 . s e
rajatag - 25 Aug 2006 12:51 GMT
Thanks for the help. I will test this out!
Regards,
Rajat
rajatag - 27 Aug 2006 10:21 GMT
Gordon, your solution worked well.
Thanks!
Rajat