Java InputStream.available () возвращает> 0 после чтения - PullRequest
0 голосов
/ 18 апреля 2019

Я создаю программу чата, в которой хосты подключаются через сокеты и общаются друг с другом с помощью потоков ObjectInput и ObjectOutput. Хост строит строку из ввода с клавиатуры и отправляет ее другим хостам вместе с массивом целых чисел.

После того, как хост успешно прочитал сообщение с помощью readObject (), цикл while (true) продолжается, и этот хост зависает при следующем вызове readObject (). Я могу только предположить, что это потому, что indata.available () возвращает true даже после чтения того, что было в нем, и когда он пытается прочитать снова, прежде чем что-то еще было отправлено, он блокирует (ждет).

Ниже приведен фрагмент соответствующего кода. Я провел некоторое исследование и обнаружил, что не могу очистить или очистить поток ввода. Я также не могу закрыть его - из-за природы постоянно работающей программы чата, она должна оставаться открытой, чтобы продолжить чтение.

Кроме того, я понимаю, что я проверяю indata.available () и затем читаю с использованием input.readObject (). Я думал, что это был правильный способ сделать это, но поправьте меня, если я ошибаюсь.

Я не уверен, что с этим делать! Мне нужно indata.available (), чтобы вернуть 0, если я не записал объект в поток.

    private InputStream[] indata;                
    private ObjectInputStream[] inputs;          
    private ObjectOutputStream[] outputs;        
    private int[] stamps;   

    // Establish connections via sockets between 3 hosts, serverless                     

    while (true) {
        // Build a message
        for (all hosts that aren't myself) {
            if ( i != rank ) {
                outputs[i].writeObject( message );
                outputs[i].writeObject( stamps );
                outputs[i].flush( ); 
                outputs[i].reset( );
            }
        }

        // Read a message in from a host that sent one
        for (all hosts that aren't myself) {
            if (indata[j].available() > 0) {
                String message = (String)inputs[j].readObject();
                int[] senderStamps = (int[])inputs[j].readObject();
            }
        }
    }

Некоторая дополнительная информация, для уточнения:

Я использую available (), потому что инструктор использовал его в своем коде, и мне не разрешено его менять. Кроме того, вызов функции available () работал так, как предполагалось, когда отправлялся только один объект (строка) - единственным кодом, который был на стороне отправки, были «writeObject» и «flush». Моя работа состояла в том, чтобы добавить код для отправки массива, и когда я делаю это, я также должен добавить код для сброса () ObjectOutputStream (или у меня возникают другие проблемы - когда массив отправляется, изменяется, а затем отправляется снова без вызова метода reset () между отправками вместо новой измененной отправляется исходная, неизмененная версия).

Я не могу просто заблокировать чтение, так как процесс, заблокированный на чтение, не может записывать на другие хосты, и мне нужно иметь возможность писать, даже если хосту нечего читать.

Кроме того, нам не разрешено использовать несколько потоков.

1 Ответ

0 голосов
/ 19 апреля 2019

Я понял, что происходит, но я не уверен, что понимаю, почему.

Когда я вызвал reset () после отправки, а затем прочитал объекты на принимающей стороне, в потоке остался еще 1 байт. Это то, что заставляло меня попадать в условие if и затем блокировать при повторном чтении (потому что на самом деле не было объекта для чтения).

Мне пришлось вызвать reset, потому что я отправлял постоянный объект (массив). Я заметил, что мне не нужно вызывать метод reset, когда я только отправляю строку, и разница между строкой и массивом заключалась в том, что массив был членом данных класса, в то время как строка создавалась заново каждый раз, когда цикл побежал.

Итак, я создал непостоянную копию массива, который я хотел отправить, и отправил эту копию. Когда я сделал это, мне не пришлось вызывать сброс (до сих пор не понимаю, почему). Кроме того, после чтения из входного потока внутри осталось 0 байтов, поэтому программа никогда не помещалась в положение, в котором readObject блокировал бы.

Мне кажется, я понимаю, почему мне не нужно выполнять сброс при отправке непостоянных объектов, но я не понимаю, почему reset () заставлял данные оставаться в соответствующем входном потоке.

В любом случае, он работает как задумано.

...