BufferedReader从未准备好(用Java编写Socket编程)

时间:2011-05-19 10:42:22

标签: java sockets bufferedreader ready

我已经将套接字声明为套接字如下:

serverAddr = InetAddress.getByName(this.ip);
socket = new Socket(serverAddr, port);
out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())), true);

但是,以下内容不起作用。 in.ready()始终返回false,如果删除,程序将冻结在String message = in.readLine();

private void receive() {
        try {
            InputStreamReader isr = new InputStreamReader(socket.getInputStream());
            System.out.println(isr.getEncoding());
            BufferedReader in = new BufferedReader(isr);
            if (in.ready()) {
                String message = in.readLine();
                if (message != null) {
                    if (listener != null) {
                        listener.receiveMessage(ip, message);
                    } else {
                        print("Client recieved: " + message);//
                    }
                }
            }
            in.close();
        } catch (Exception e) {
            print("Error with input stream: " + e);
            disconnect();
        }

    }

我怎么能解决这个问题?

编辑:

这就是我的服务器类中的发送方式: 通过out.println(消息); 了out.flush(); 每当我在消息中放入某些内容时,就会发生这种情况。在这个循环之后关闭。

4 个答案:

答案 0 :(得分:4)

您不应该像这样使用ready()javadoc说明了这一点:

  

“返回:如果保证下一个read()不阻止输入,则返回true,否则返回false。注意,返回false并不能保证下一次读取将阻塞。”

您的代码隐含地假设ready() -> false表示下一个read将阻止。实际上,这意味着下一个read 可能会或可能不会阻止。

正如@EJP所说......只需拨打read电话。


  

我该怎么办才能阻止阻挡?如果被阻止,客户端将无法发送任何内容

如果读取中的阻塞是您的应用程序的问题,请使用单独的线程进行读取,或更改代码以使用NIO通道选择器。

答案 1 :(得分:2)

只需删除in.ready()测试即可。它没有帮助你。 readLine()将阻塞,直到有可用数据。如果还没有数据到达,你打算做什么?

答案 2 :(得分:1)

我想到了三件事:

  • 您将在每次receive调用中重新打开输入流,并将其包装到BufferedReader中。这可能会在缓冲区中读取多行,并且在完成(关闭它)之后,剩余的缓冲字节将不再可用于后续的receive调用
  • 您是否考虑过使用自己的线程来阅读服务器消息?如果被阻止,它就不会受到伤害
  • 在写入数据后关闭套接字的一侧并立即关闭它时,我遇到了一些问题。有时并非所有数据都被另一方收到,尽管有flush()close()来电。在你的情况下,这也是一个问题

修改
in引用保留在receive方法之外,并不能完全解决您的问题。您应该使用while循环来读取所有缓冲的消息并为每个人调用侦听器,例如:

if (in.ready()) {
    String message;
    while ((message = in.readLine()) != null) {
        // ...
    }
 }

但请注意,最后一行可能是部分阅读的消息(例如,3和1/2消息被缓冲)。如果这是一个问题,您可以读取消息char-by-char以确定行何时结束,并使用PushbackReader来放回不完整的消息。

答案 3 :(得分:0)

您可能需要致电out.flush()以清除BufferedWriter

中的任何内容