当我的 InputStream 定期接收数据时,它的消息如何永远不会为空?
How my InputStream's message is never null when it is receiving data periodically?
我想要服务器-客户端关系。一旦 client 连接到 server,server 每 1.5 秒向客户端发送一条消息。为简单起见,Server 不对来自 client 的消息执行任何操作。在 客户端的 代码中,我想使用 System.in
将消息发送到 服务器 (这没有任何意义),当我发送它,我想阅读 服务器的 响应(来自 服务器 的所有累积消息)。代码不是片段,而是“真正的代码”。
客户:
public class ClientClass {
public static final String IP_ADDRESS = "127.0.0.1";
public static final int PORT = 9090;
public static void main (String[] args) throws IOException {
Socket socket = new Socket (IP_ADDRESS,PORT);
PrintWriter output = new PrintWriter (socket.getOutputStream (),true);
BufferedReader input = new BufferedReader (new InputStreamReader (socket.getInputStream ()));
BufferedReader keyboard = new BufferedReader (new InputStreamReader (System.in));
while (true){
System.out.println ("Enter message you want to send to server:");
String msg = keyboard.readLine ();
output.println (msg);
String serverResponses = input.readLine ();
while (serverResponses!=null){
System.out.println (serverResponses);
serverResponses=input.readLine ();
}
}
}
}
服务器:
public class ServerClass {
public static int PORT = 9090;
public static void main (String[] args) throws IOException, InterruptedException {
ServerSocket server = new ServerSocket (PORT);
Socket client = server.accept ();
PrintWriter output = new PrintWriter (client.getOutputStream (),true);
while (true){
output.println ("hello from server");
Thread.sleep (1500);
}
}
}
//我的评论:client中的readLine()
方法是blocking,所以看不懂服务器的消息,直到我真正从键盘上读到一些东西。这就是为什么我要循环“拾取”inputStream
中的所有行。我希望一旦我阅读了所有行,变量 stringResponses
就会得到 null 并从内部 while 循环中中断。然后我想我会在外循环中找到“输入要发送到服务器的消息”的打印到控制台。不幸的是,我的代码从未从内部 while 循环中跳出,我想知道为什么。当我每 1.5 秒写入一个流时,它怎么从来没有 null,这意味着它有足够的时间为 null 并从循环中中断。
实际输出:
Enter message you want to send to server:
hey! //this is what I typed
hello from server
hello from server
hello from server
//these three popped immediately, as they accumulated.
hello from server
hello from server
hello from server
hello from server
//keeps printing "hello from server" every 1.5s and never comes back to "enter your message" -WHY?
readLine
return 流末尾为空。由于服务器套接字未关闭。它在你的内部循环中永远不会为 null。
Link - https://docs.oracle.com/javase/7/docs/api/java/io/BufferedReader.html#readLine()
A String containing the contents of the line, not including any
line-termination characters, or null if the end of the stream has been
reached
当 readLine
在键盘对象的循环中被调用时,您期望什么行为?
String msg = keyboard.readLine();
while(msg != null)
msg = keyboard.readLine();
这也将继续从 System.in
获取输入。循环永远不会结束。
解决方案
如上文 java 文档所述,readLine
方法块用于输入。这就是原因,没有延迟服务器响应的效果。方法 returns null
仅在流的末尾。
解决方案 1 - 利用就绪方法
ready
方法 returns false 当读取方法必须等待输入数据时。由于服务器代码休眠 1.5 秒,此方法在此期间应 return false。
这种方法的缺点是,如果服务器没有按时完成所有响应行,那么您收集所有服务器响应的内部循环将会中断。
while (true){
System.out.println ("Enter message you want to send to server:");
String msg = keyboard.readLine ();
output.println (msg);
String serverResponses = input.readLine ();
System.out.println (serverResponses);
while (input.ready()){
serverResponses=input.readLine ();
System.out.println (serverResponses);
}
}
解决方案 2 - 服务器发送总行数
如果服务器知道总行数,则可以将其作为流中的第一行发送。根据总行数,客户端代码可以读取那么多行。这种方法的缺点是必须在服务器响应中添加额外的一行。
while (true){
System.out.println ("Enter message you want to send to server:");
String msg = keyboard.readLine ();
output.println (msg);
Integer linesCount = Integer.parseInt(input.readLine ());
for (int i=0; i< linesCount; i++){
String serverResponses=input.readLine ();
System.out.println (serverResponses);
}
}
我想要服务器-客户端关系。一旦 client 连接到 server,server 每 1.5 秒向客户端发送一条消息。为简单起见,Server 不对来自 client 的消息执行任何操作。在 客户端的 代码中,我想使用 System.in
将消息发送到 服务器 (这没有任何意义),当我发送它,我想阅读 服务器的 响应(来自 服务器 的所有累积消息)。代码不是片段,而是“真正的代码”。
客户:
public class ClientClass {
public static final String IP_ADDRESS = "127.0.0.1";
public static final int PORT = 9090;
public static void main (String[] args) throws IOException {
Socket socket = new Socket (IP_ADDRESS,PORT);
PrintWriter output = new PrintWriter (socket.getOutputStream (),true);
BufferedReader input = new BufferedReader (new InputStreamReader (socket.getInputStream ()));
BufferedReader keyboard = new BufferedReader (new InputStreamReader (System.in));
while (true){
System.out.println ("Enter message you want to send to server:");
String msg = keyboard.readLine ();
output.println (msg);
String serverResponses = input.readLine ();
while (serverResponses!=null){
System.out.println (serverResponses);
serverResponses=input.readLine ();
}
}
}
}
服务器:
public class ServerClass {
public static int PORT = 9090;
public static void main (String[] args) throws IOException, InterruptedException {
ServerSocket server = new ServerSocket (PORT);
Socket client = server.accept ();
PrintWriter output = new PrintWriter (client.getOutputStream (),true);
while (true){
output.println ("hello from server");
Thread.sleep (1500);
}
}
}
//我的评论:client中的readLine()
方法是blocking,所以看不懂服务器的消息,直到我真正从键盘上读到一些东西。这就是为什么我要循环“拾取”inputStream
中的所有行。我希望一旦我阅读了所有行,变量 stringResponses
就会得到 null 并从内部 while 循环中中断。然后我想我会在外循环中找到“输入要发送到服务器的消息”的打印到控制台。不幸的是,我的代码从未从内部 while 循环中跳出,我想知道为什么。当我每 1.5 秒写入一个流时,它怎么从来没有 null,这意味着它有足够的时间为 null 并从循环中中断。
实际输出:
Enter message you want to send to server:
hey! //this is what I typed
hello from server
hello from server
hello from server
//these three popped immediately, as they accumulated.
hello from server
hello from server
hello from server
hello from server
//keeps printing "hello from server" every 1.5s and never comes back to "enter your message" -WHY?
readLine
return 流末尾为空。由于服务器套接字未关闭。它在你的内部循环中永远不会为 null。
Link - https://docs.oracle.com/javase/7/docs/api/java/io/BufferedReader.html#readLine()
A String containing the contents of the line, not including any line-termination characters, or null if the end of the stream has been reached
当 readLine
在键盘对象的循环中被调用时,您期望什么行为?
String msg = keyboard.readLine();
while(msg != null)
msg = keyboard.readLine();
这也将继续从 System.in
获取输入。循环永远不会结束。
解决方案
如上文 java 文档所述,readLine
方法块用于输入。这就是原因,没有延迟服务器响应的效果。方法 returns null
仅在流的末尾。
解决方案 1 - 利用就绪方法
ready
方法 returns false 当读取方法必须等待输入数据时。由于服务器代码休眠 1.5 秒,此方法在此期间应 return false。
这种方法的缺点是,如果服务器没有按时完成所有响应行,那么您收集所有服务器响应的内部循环将会中断。
while (true){
System.out.println ("Enter message you want to send to server:");
String msg = keyboard.readLine ();
output.println (msg);
String serverResponses = input.readLine ();
System.out.println (serverResponses);
while (input.ready()){
serverResponses=input.readLine ();
System.out.println (serverResponses);
}
}
解决方案 2 - 服务器发送总行数
如果服务器知道总行数,则可以将其作为流中的第一行发送。根据总行数,客户端代码可以读取那么多行。这种方法的缺点是必须在服务器响应中添加额外的一行。
while (true){
System.out.println ("Enter message you want to send to server:");
String msg = keyboard.readLine ();
output.println (msg);
Integer linesCount = Integer.parseInt(input.readLine ());
for (int i=0; i< linesCount; i++){
String serverResponses=input.readLine ();
System.out.println (serverResponses);
}
}