7

我的套接字已经像这样声明了套接字:

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(message); out.flush(); 每当我在消息中放入某些内容时,这都会在循环中发生。out 在此循环之后关闭。

4

4 回答 4

4

你不应该这样使用ready()javadoc是这样说的:

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

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

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


我能做些什么来防止阻塞呢?如果被阻止,客户端将无法发送任何内容

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

于 2011-05-19T10:58:50.257 回答
2

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

于 2011-05-19T10:45:00.477 回答
1

我想到了3件事:

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

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

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

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

于 2011-05-19T11:09:21.253 回答
0

你可能需要打电话out.flush()来冲洗任何东西BufferedWriter

于 2011-05-19T10:49:03.450 回答