SocketChannel запускает isReadable (), но читать нечего - PullRequest
3 голосов
/ 10 ноября 2010

У меня новая проблема с моим приложением для 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;
}

Теперь он застревает в бесконечном цикле. Остальные байты никогда не получают <0, потому что нечего читать, а bytesRead остается 0. </p>

Мой вопрос: почему isReadable true, когда читать нечего?

Ответы [ 2 ]

2 голосов
/ 12 мая 2014

Выбранный ключ выбора должен быть удален из набора, возвращаемого селектором.

Думаю, эта статья поможет вам понять.

Почему ключ должен быть удален в `selector.selectedKeys (). Iterator ()` в java nio?

2 голосов
/ 10 ноября 2010

Если bytesRead <0, вы должны закрыть канал или хотя бы отменить регистрацию OP_READ.В противном случае вы будете получать OP_READ снова и снова, чтобы рассказать вам о EOS. </p>

Вы не должны выделять свой ByteBuffer один раз для чтения.Выделение ByteBuffers - дорогостоящая операция.По крайней мере, выделите его один раз для каждой записи в метод чтения.Еще лучше, выделите по одному на канал, когда вы принимаете его.Вы можете сохранить его как или через вложение ключа, чтобы не потерять его, и оно исчезнет при отмене ключа или закрытии канала.

...