سؤال

لدي مشكلة جديدة مع تطبيق 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 التطبيق لذلك أنا بحاجة إلى إرسال وتلقي مصافحة. إرسال واستلام المصافحة يعمل مع هذا أثناء الحلقة. لأول مرة 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.

سؤالي هو لماذا يكون صحيحًا عندما لا يوجد شيء يمكن قراءته؟

هل كانت مفيدة؟

المحلول

إذا كان BytesRead <0 ، فيجب عليك إغلاق القناة أو على الأقل تحرير OP_READ. وإلا فإنك ستستمر في الحصول على OP_READ مرارًا وتكرارًا لتخبرك عن EOS.

يجب ألا تخصص Bytebuffer مرة واحدة لكل قراءة. تخصيص Bytebuffers هي عملية باهظة الثمن. على الأقل تخصيصه مرة واحدة لكل إدخال إلى طريقة القراءة. والأفضل من ذلك ، تخصيص واحدة لكل قناة عند قبولها. يمكنك الاحتفاظ به ، أو عبر ، مرفق المفتاح حتى لا تفقده ، وبالتالي يختفي عند إلغاء المفتاح أو إغلاق القناة.

نصائح أخرى

يجب إزالة مفتاح التحديد الذي تمت قراءته جميعًا من المجموعة التي تم إرجاعها بواسطة Selector.

أعتقد أن هذا المقال سيساعدك على الفهم.

لماذا يجب إزالة المفتاح في `selector.selectedkeys (). iterator ()` في Java Nio؟

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top