BufferedReader readLine пропускает каждую вторую строку

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

Код клиента:

    ...

    out.println(console.readLine());                //Client initiates (sent to server)

    while ((userOut = in.readLine()) != null)       //Waits for response
    {
        System.out.println("Server says: " + userOut);  //Prints response

        userIn = console.readLine();                //Gets user input
        out.println(userIn);                        //Sends user input to server
    }

    ...

Код серверов:

    ...

    while ((clientIn = in.readLine()) != null)  //Waits for clients message
    {
        System.out.println("Client says: " + clientIn); //Print clients message

        //Send appropriate response
        if (clientIn.equals(CLIENT_INSTRUCTION_LOGCALC))
        {
            out.println(SERVER_RESPONSE_LOGCALC_OK); //Send response to client
            System.out.println("Message sent: " + SERVER_RESPONSE_LOGCALC_OK); //Print response sent
        }

        else if (clientIn.equals(CLIENT_INSTRUCTION_SB))
        {
            out.println(SERVER_RESPONSE_SB_CHANGE);
        }

        else if (clientIn.equals(CLIENT_INSTRUCTION_BYE))
        {
            out.println(SERVER_RESPONSE_BYE_OK);
        }

        else if (clientIn.equals(CLIENT_INSTRUCTION_END))
        {
            out.println(SERVER_RESPONSE_END_OK);
        }

        else
        {
            out.println(SERVER_RESPONSE_INPUT_ERR);
        }
        ...

Пример использования этого дисплея (сначала клиент):

 LOGCALC
 Server says: LOGCALC: OK
 LOGCALC
 Server says: 

Сервер:

Client says: LOGCALC
Message sent: LOGCALC: OK

Client says: LOGCALC
Message sent: LOGCALC: OK

Надеюсь, вы видите, что во втором сообщении LOGCALC, отправленном на сервер, сервер ответил, но клиент не получил ответа сервера.

Есть предположения?


person Brad    schedule 26.08.2011    source источник
comment
Но ответ получил, не так ли? В противном случае Сервер говорит: часть тоже не должна появляться.   -  person Christian.K    schedule 26.08.2011


Ответы (3)


Глядя на ваш вывод, кажется, что у вас есть дополнительный перенос строки в SERVER_RESPONSE_LOGCALC_OK, поскольку у System.out.println("Message sent: " + SERVER_RESPONSE_LOGCALC_OK); есть дополнительная строка после него в выводе сервера. Я бы удалил лишнюю новую строку или использовал простой out.print(SERVER_RESPONSE_LOGCALC_OK) вместо out.println(SERVER_RESPONSE_LOGCALC_OK);. Это должно решить вашу проблему с пропуском.

Основной недостаток, с которым вы столкнулись, заключается в том, что вы читаете только одну строку за раз и затем ждете ввода пользователя перед чтением другой строки вместо того количества строк, которое доступно, прежде чем ждать ввода пользователя. Держу пари, что если вы выполните в клиенте что-то вроде приведенного ниже кода, вы увидите другой результат.

out.println(console.readLine());                //Client initiates (sent to server)

    while ((userOut = in.readLine()) != null)       //Waits for response
    {
        System.out.println("Server says: " + userOut);  //Prints response

        if(!in.available()){
          userIn = console.readLine();                //Gets user input
          out.println(userIn);                        //Sends user input to server
        }
    }
person Femi    schedule 26.08.2011
comment
available () нельзя использовать для этой цели, так как некоторая часть ответа сервера может быть задержана сетью. - person x22; 26.08.2011
comment
available делает именно то, что написано: проверяет, есть ли данные для чтения. Данные, задержанные сетью, недоступны. Альтернативный вариант - переместить цикл сетевого чтения в отдельный поток, чтобы можно было заблокировать вызов readLine сетевого сокета, не блокируя вызов readLine консоли. - person Femi; 26.08.2011

Клиент определенно получает «какое-то» сообщение, отсюда напечатанная часть «Сервер говорит». Кажется, что дополнительная новая строка была каким-то образом написана сервером при отправке «первого ответа» клиенту, что приводит к чтению пустой строки на второй итерации. Во втором случае стоило бы проверить / отладить значение userOut.

Кроме того, я не уверен, было ли это намеренно, но я вижу пустую строку в случае вывода сервера. Предполагая, что весь вывод выполняет опубликованный фрагмент кода, откуда берется эта дополнительная новая строка?

person Sanjay T. Sharma    schedule 26.08.2011

readLine ()

сканирует \ r \ n, только \ r или только \ n.

я думаю, сервер может ответить \ n \ r-linebreak, в этом случае вы станете вашим двойным разрывом строки (один для \ n, другой для \ r).

Насколько я понимаю, это не может быть проблемой для функциональности вашего кода. Итак, чтобы пропустить проблему регистрации: вы можете проверить наличие пустого userOut (проверка по пустоте).

person Grim    schedule 26.08.2011