BufferedReader 从未准备好(Java 中的 Socket 编程)
我已经像这样声明了套接字:
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();
}
}
我该如何解决这个问题?
编辑:
这就是我的服务器类中的发送方式: 输出.println(消息); 出.flush(); 每当我在消息中放入某些内容时,就会循环发生这种情况。 out 在这个循环之后被关闭。
I have socket already declared socket like this:
serverAddr = InetAddress.getByName(this.ip);
socket = new Socket(serverAddr, port);
out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())), true);
however, the following doesn't work. in.ready()
always returns false and if removed the program will freeze at 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();
}
}
How could i solve this?
EDIT:
This is how sending looks like in my server class:
out.println(message);
out.flush();
This happens in a loop whenever i've put something in message. out is closed after this loop.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
您不应该像这样使用
ready()
。 javadoc 说这:您的代码隐式假设
ready() -> ; false
表示下一个读取
将被阻塞。事实上,这意味着下一个读取
可能会或可能不会阻塞。正如 @EJP 所说...只需执行
read
调用即可。如果读取阻塞对您的应用程序来说是一个问题,请使用单独的线程来执行读取,或者更改代码以使用 NIO 通道选择器。
You shouldn't be using
ready()
like this. The javadoc says this:Your code is implicitly assuming that
ready() -> false
means that the nextread
will block. In actual fact, it means the nextread
might or might not block.As @EJP says ... just do the
read
call.If blocking in read is a problem for your application, either use a separate thread to do the reading, or change your code to use NIO channel selectors.
只需删除 in.ready() 测试即可。这对你没有帮助。 readLine() 将阻塞,直到有数据可用。如果还没有数据到达,您还打算做什么?
Just remove the in.ready() test. It isn't helping you. readLine() will block until there is data available. What else were you planning to do if no data has arrived yet?
我想到了三件事:
receive
调用中重新打开输入流,并将其包装到BufferedReader
中。这可能会在缓冲区中读取不止一行,并且在完成(关闭它)后,剩余的缓冲字节将不再可用于后续的receive
调用flush()
和close()
,但另一方并未收到所有数据。也许这也是您遇到的问题编辑:
简单地将
in
引用保留在receive
方法之外并不能完全解决您的问题。您应该使用 while 循环来读取所有缓冲的消息并为每个人调用侦听器,例如:但请注意最后一行可能是部分读取的消息(例如 3 和 1/2 消息被缓冲)。如果这是一个问题,您可以逐个字符地读取消息以确定行何时结束,并使用
PushbackReader
放回不完整的消息。There are 3 things that come to my mind:
receive
call, and wrapping it into aBufferedReader
. This might read more than a single line into the buffer, and after finishing (closing it), the remaining buffered bytes will no longer be available for subsequentreceive
callsflush()
andclose()
calls. Maybe this is also an issue in your situationEdit:
Smiply keeping the
in
reference outside of thereceive
method will not fully solve your problem. You should use a while loop for reading all buffered messages and call the listener for everyone, e.g.:But watch out as the last line might be a partially read message (e.g. 3 and 1/2 messages were buffered). If this is an issue, you could read the messages char-by-char for determining when a line ends, and use a
PushbackReader
for putting back incomplete messages.您可能需要调用
out.flush()
来刷新BufferedWriter
中的任何内容You may need to call
out.flush()
to flush anything inBufferedWriter