问题
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.becomesReadable(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?
回答1:
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.
回答2:
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.
来源:https://stackoverflow.com/questions/7676799/socketchannel-read-blocks-indefinitely