SocketChannel.read() blocks indefinitely
I'm having a hard time figuring this one out. I have the following code:
if (selector.select(1000) <= 0) {
return;
}
Set<SelectionKey> selectionKeys = selector.selectedKeys();
for (SelectionKey key : selectionKeys) {
try {
SocketEventHandler handler = (SocketEventHandler) key.attachment();
if (key.isValid() && key.isAcceptable()) {
handler.becomesAcceptable(key);
}
if (key.isValid() && key.isReadable()) {
handler.becomesReadab开发者_如何学Gole(key);
}
if (key.isValid() && key.isWritable()) {
handler.becomesWritable(key);
}
if (key.isValid() && key.isConnectable()) {
handler.becomesConnectable(key);
}
} catch (IOException e) {
key.cancel();
}
}
selector.selectedKeys().clear();
With the following Handler code for reads:
synchronized public void becomesReadable(SelectionKey key) throws IOException {
ByteBuffer temporaryBuffer = ByteBuffer.allocate(DEFAULT_BYTE_BUFFER_SIZE);
temporaryBuffer.position(0);
int read = -1;
try {
read = channel.read(temporaryBuffer);
} catch (IOException e) {
prefixLogger.debug("Trace:", e);
close();
}
...
}
And that's the only point where the handler function is ever called. So if I ever get into the becomeReadable()
function the channel is in readable state, yet the call to read()
blocks without ever returning. Is there something I missed?
I'm wondering why that becomesReadable() method is synchronized. The less synchronization when using NIO the better.
I'm also wondering why you're not logging the IOException, and why you're just cancelling the key instead of closing the channel. So I'm also wondering what I/O exceptions you are getting that you don't know about.
Also allocating buffers is quite expensive: you shouldn't do that on every read, you should have one as session state in the SocketEventHandler instance allocated to the channel.
Did you call channel.configureBlocking( false )
somewhere in your code?
It's hard to tell what kind of channel you are using here, but I think SocketChannel
is created in blocking mode originally.
精彩评论