4

我的 Android 应用程序出现了新问题。SocketChannel告诉我它,但isReadable()没有什么可读的。

while(running)
    {
        int readyChannels = 0;
        try {
            readyChannels = selector.select();
        } catch (IOException e) {
            e.printStackTrace();
        }

        if(readyChannels == 0) continue;

        Set<SelectionKey> selectedKeys = selector.selectedKeys();
        Iterator<SelectionKey> keyIterator = selectedKeys.iterator();

        while(keyIterator.hasNext())
        {
            SelectionKey key1 = keyIterator.next();

            if(key1.isReadable())
            {
                publishProgress(1);
            }

            else if(key1.isWritable())
            {
                publishProgress(2);
            }

            else if(!key1.isValid())
            {
                Log.e("State", "progress error");
                publishProgress(3);
            }
        }
    }

我在onProgressUpdate. 这是一个WebSocket应用程序,所以我需要发送和接收握手。使用此 while 循环发送和接收握手。首先SelectionKey.isWriteable()发送和握手,然后SelectionKey.isReadable()读取和握手。但那SelectionKey.isReadable()仍然是真的。现在调用正常的读取函数(不是readHandshake)函数。但是没有什么可读的。这是我的读取功能的代码:

public byte[] read(int nBytes)
{
    Log.e("State", "public byte[] read(int nBytes) start");

    byte[] resultData = new byte[1024];
    ByteBuffer data = ByteBuffer.wrap(resultData);
    int remainingBytes = nBytes;

    while(remainingBytes >= 0)
    {
        ByteBuffer buffer = ByteBuffer.allocate(1024);
        int bytesRead = 0;
        try {
            bytesRead = channel.read(buffer);
        } catch (IOException e) {
            Log.e("ERROR", "channel read");
        }

        if(bytesRead < 0)
        {
            sockState = WebSocketState.WebSocketErrorOccurred;
        }

        else
        {
            remainingBytes = remainingBytes - bytesRead;
            data.put(buffer.array(), 0, bytesRead);
        }
    }

    Log.e("State", "public byte[] read(int nBytes) done");

    return resultData;
}

现在它陷入了无休止的while循环。remainingBytes 永远不会 < 0,因为没有要读取的内容,并且 bytesRead 保持为 0。

我的问题是为什么 isReadable 在没有什么可读的时候是真的?

4

2 回答 2

2

如果 bytesRead < 0 您应该关闭通道或至少取消注册 OP_READ。否则你会一遍又一遍地获取 OP_READ 来告诉你关于 EOS 的信息。

您不应该在每次读取时分配一次 ByteBuffer。分配 ByteBuffers 是一项昂贵的操作。每个条目至少将其分配给 read 方法一次。更好的是,在您接受时为每个频道分配一个。您可以将其保留为或通过密钥附件保留,以免丢失它,因此当您取消密钥或关闭频道时它会消失。

于 2010-11-10T01:24:10.233 回答
2

已读取的 SelectionKey 应从 Selector 返回的集合中删除。

我想这篇文章会帮助你理解。

为什么要在 java nio 的`selector.selectedKeys().iterator()` 中删除键?

于 2014-05-12T02:41:15.513 回答