Java BufferedReader, как вызывать, только если не блокируется?

У меня есть 2 сокета, и я использую BufferedReader для его входных потоков. То, что я пытаюсь сделать, это взять все входные данные из первого сокета и отправить их в другой сокет (и наоборот).

Проблема в том, что если первый сокет не отправляет сообщение, он все равно будет блокироваться на первом readLine(), даже если второй сокет уже отправил некоторые данные и готов. Я хотел бы продолжить этот простой подход без использования дополнительных потоков.

Вот некоторый код, который я написал, как вы можете видеть, у меня есть 2 BufferedReaders (in0 и in1), программа зависает на in0.readLine() (блокировка).

private void network()
{
    PrintWriter out0 = null, out1 = null;
    BufferedReader in0 = null,in1 = null;
    try{
            //clients[] is an array of Socket[2]
        in0 = new BufferedReader(new InputStreamReader(clients[0].getInputStream()));
        out0 = new PrintWriter(clients[0].getOutputStream(), true);
        in1 = new BufferedReader(new InputStreamReader(clients[1].getInputStream()));
        out1 = new PrintWriter(clients[1].getOutputStream(), true);
      } catch (IOException e) {
        System.out.println("Accept failed: 4445");
        System.exit(-1);
      }

    int count = 1;
    while(true)
    {
        System.out.println("network check loop # " + count);
        ++count;
        String nextMessage = null;
        try {
            if( (nextMessage = in0.readLine()) != null)
            {
                this.relayMessage(nextMessage,out1);
            }
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        System.out.println("Middle of network check loop");
        nextMessage = null;

        try {
            if((nextMessage = in1.readLine()) != null)
            {
                this.relayMessage(nextMessage,out0);
            }
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
}

Как я могу просто пропустить этот оператор, если in0 не готов предоставить мне некоторые данные? Я видел метод ready() BufferedReader и пытался использовать in0.ready() && readLine(), но это приводит к бесконечному циклу, поскольку ни один из буферизованных считывателей никогда не оказывается «готовым». Кроме того, я уверен, что сообщения, отправляемые через сокет, заканчиваются символами новой строки, поэтому функция readLine() должна работать корректно!

Любые идеи?


person Community    schedule 26.03.2012    source источник


Ответы (3)


Попробуйте использовать setSoTimeout, чтобы поставить тайм-аут на ваш read(), тогда вам просто нужно перехватить исключение SocketTimeoutException, если время таймера истекло.

person NeeL    schedule 26.03.2012
comment
Звучит как отличная идея, я попробую - person ; 26.03.2012
comment
Также посмотрите, что такое неблокирующий сокет, он связан с setSoTimeout и может быть тем, что вы ищете. (в гугле вы найдете множество примеров) - person NeeL; 26.03.2012

Здесь ключевые слова break и continue — ваши друзья.

person Chandra Sekhar    schedule 26.03.2012

Самый простой подход — использовать два потока. Таким образом, вам не нужно писать собственный код планирования, чтобы определить, какой поток должен выполняться. Кстати: код для копирования из одного сокета в другой одинаков в каждом потоке, что уменьшает дублирование.

Для управления вашими потоками я бы использовал ExecutorService, который упростит закрытие потоков.

person Peter Lawrey    schedule 26.03.2012