SocketChannel.read() blocks indefinitely

坚强是说给别人听的谎言 提交于 2019-12-24 15:22:35

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!