SocketChannel触发isReadable()但没什么可读的

时间:2010-11-09 22:24:04

标签: java android sockets nio socketchannel

我的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;
}

现在它陷入无休止的循环中。 remainingBytes永远不会得到&lt; 0因为没有要读取的内容而且bytesRead保持为0。

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

2 个答案:

答案 0 :(得分:2)

如果bytesRead&lt; 0你应该关闭频道或至少取消注册OP_READ。否则你将一遍又一遍地获得OP_READ以告诉你EOS。

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

答案 1 :(得分:2)

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

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

Why the key should be removed in `selector.selectedKeys().iterator()` in java nio?