【问题标题】:BufferedReader readLine skipping every second lineBufferedReader readLine 每隔两行跳过一次
【发布时间】:2011-11-04 06:06:04
【问题描述】:

我正在使用套接字在服务器和客户端之间进行通信。 但出于某种原因,客户端会跳过服务器发送的每一行。

客户代码:

    ...

    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 消息中,服务器响应了,但客户端没有收到服务器响应。

有什么想法吗?

【问题讨论】:

  • 但它确实收到了响应,不是吗?否则“服务器说:”部分也不应该出现。

标签: java sockets bufferedreader


【解决方案1】:

查看您的输出,您似乎在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
        }
    }

【讨论】:

  • available() 不能用于此目的,因为服务器回复的某些部分可能会被网络延迟。
  • available 就像它所说的那样:查看是否有数据可供读取。网络延迟的数据不可用。另一种方法是将网络读取循环移动到一个单独的线程中,这样您就可以阻塞网络套接字 readLine 调用,而不会阻塞控制台 readLine 调用。
【解决方案2】:

客户端肯定会收到“某种”消息,因此会打印“服务器说”部分。似乎服务器在向客户端发送“第一个响应”时以某种方式编写了一个额外的新行,这导致在第二次迭代中读取一个空字符串。在第二种情况下,值得检查/调试userOut 的值。

另外,我不确定这是否是故意的,但在服务器输出的情况下我看到一个空行。假设它是发布的代码 sn-p 进行所有输出,那么额外的换行符是从哪里来的?

【讨论】:

    【解决方案3】:

    readLine()

    仅按 \r 或仅按 \n 扫描 \r\n。

    我认为,服务器可能会通过\n\r-换行符来回答,在这种情况下,你将成为你的双换行符(一个用于\n,另一个用于\r)。

    据我所知,这可能不是代码功能的问题。 因此,要跳过日志记录问题:您可以检查空的 userOut(按空性检查)。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-10-02
      • 2012-05-02
      • 1970-01-01
      • 2014-06-07
      • 1970-01-01
      • 2012-04-18
      • 2015-08-27
      相关资源
      最近更新 更多