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()

  1. A scanner.hasNext() 读取,直到可以检测到下一个标记的 beginning。这并不意味着整个令牌已被读取或接收。但是 scanner.next() 必须读取所有令牌;因此它可能会阻塞。

  2. 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());
}