java 扫描器在 .next() 不应该阻塞时阻塞
java scanner blocks at .next() when it shouldn't
我正在创建一个简单的 Server/Client 应用程序。服务器将 socket.getInputStream()
包装在 Scanner
中。客户端从 System.in
获取用户输入并使用 PrintWriter
将其发送到服务器。服务器评估 scanner.hasNext()
为真,但它会在接下来的 scanner.next()
调用时阻塞。根据 javadocs:
This method may block while waiting for input to scan, even if a previous invocation of hasNext() returned true.
嗯..这有什么意义? 编辑: 值得注意的是,当客户端终止时,服务器现在继续调用 scanner.next()
。奖励问题:客户端使用 autoFlush
参数将 PrintWriter
实例化为 true
,但我需要在每次调用 .write()
后刷新。为什么?这是我的代码的 MCV:
import java.io.IOException;
import java.net.ServerSocket;
import java.util.Scanner;
public class MCVServer {
public static void main(String[] args) throws IOException {
ServerSocket server = new ServerSocket(1337);
Scanner fromClient = new Scanner(server.accept().getInputStream());
while (fromClient.hasNext()) {
System.out.println("server heard something: ");
System.out.println(fromClient.next());
}
}
}
import java.io.IOException;
import java.io.PrintWriter;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.Scanner;
public class MCVClient {
public static void main(String[] args) throws UnknownHostException, IOException {
Socket socket = new Socket("localhost", 1337);
Scanner input = new Scanner(System.in);
PrintWriter output = new PrintWriter(socket.getOutputStream(), true);
while(true) {
output.write(input.next());
output.flush();
}
}
}
使用 NextLine() 而不是 Next()
A scanner.hasNext() 读取,直到可以检测到下一个标记的 beginning。这并不意味着整个令牌已被读取或接收。但是 scanner.next() 必须读取所有令牌;因此它可能会阻塞。
Autoflush 仅在调用方法 println、printf 或 format 后有效。
方法 next() 和 hasNext() 的行为按预期工作。 hasNext 方法在到达流的末尾后只会 return false 。 next() 方法将阻塞,以防它仍未到达流的末尾或正在等待输入。
加分题也很简单。根据 PrintWriter class:
的文档
Unlike the PrintStream class, if automatic flushing is enabled it will be done only when one of the println, printf, or format methods is invoked, rather than whenever a newline character happens to be output. These methods use the platform's own notion of line separator rather than the newline character.
因此,为了使用自动刷新,您需要将 write 方法替换为 println:
while (true) {
output.println(input.next());
}
我正在创建一个简单的 Server/Client 应用程序。服务器将 socket.getInputStream()
包装在 Scanner
中。客户端从 System.in
获取用户输入并使用 PrintWriter
将其发送到服务器。服务器评估 scanner.hasNext()
为真,但它会在接下来的 scanner.next()
调用时阻塞。根据 javadocs:
This method may block while waiting for input to scan, even if a previous invocation of hasNext() returned true.
嗯..这有什么意义? 编辑: 值得注意的是,当客户端终止时,服务器现在继续调用 scanner.next()
。奖励问题:客户端使用 autoFlush
参数将 PrintWriter
实例化为 true
,但我需要在每次调用 .write()
后刷新。为什么?这是我的代码的 MCV:
import java.io.IOException;
import java.net.ServerSocket;
import java.util.Scanner;
public class MCVServer {
public static void main(String[] args) throws IOException {
ServerSocket server = new ServerSocket(1337);
Scanner fromClient = new Scanner(server.accept().getInputStream());
while (fromClient.hasNext()) {
System.out.println("server heard something: ");
System.out.println(fromClient.next());
}
}
}
import java.io.IOException;
import java.io.PrintWriter;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.Scanner;
public class MCVClient {
public static void main(String[] args) throws UnknownHostException, IOException {
Socket socket = new Socket("localhost", 1337);
Scanner input = new Scanner(System.in);
PrintWriter output = new PrintWriter(socket.getOutputStream(), true);
while(true) {
output.write(input.next());
output.flush();
}
}
}
使用 NextLine() 而不是 Next()
A scanner.hasNext() 读取,直到可以检测到下一个标记的 beginning。这并不意味着整个令牌已被读取或接收。但是 scanner.next() 必须读取所有令牌;因此它可能会阻塞。
Autoflush 仅在调用方法 println、printf 或 format 后有效。
方法 next() 和 hasNext() 的行为按预期工作。 hasNext 方法在到达流的末尾后只会 return false 。 next() 方法将阻塞,以防它仍未到达流的末尾或正在等待输入。
加分题也很简单。根据 PrintWriter class:
的文档Unlike the PrintStream class, if automatic flushing is enabled it will be done only when one of the println, printf, or format methods is invoked, rather than whenever a newline character happens to be output. These methods use the platform's own notion of line separator rather than the newline character.
因此,为了使用自动刷新,您需要将 write 方法替换为 println:
while (true) {
output.println(input.next());
}