Scanner.nextLine() 在使用来自Socket的InputStream时被阻塞

7
当我直接使用Socket.getInputStream()(不使用类似Scanner这样的接口)接收数据时,它不会阻塞。但是,当我尝试使用Scanner(类似于从System.in接收字符串的方式)时,它会被阻塞。我想知道这个原因,以及连接的Socket提供给您的InputStream与System中的InputStream in有何不同。
用于测试的客户端(用于两个服务器)
导致阻塞的代码:
public class Server {

    public static void main(String[] args) {
        try {
            ServerSocket ss = new ServerSocket(15180);
            Socket socket = ss.accept();

            Scanner scanner = new Scanner(socket.getInputStream());
            //read data from client
            while(true) {
                String data = scanner.nextLine();
                System.out.println("Received data!");
            }

        }catch(IOException e) {
            e.printStackTrace();
        }
    }
}

不阻塞的代码:

public class Server {
    public static void main(String[] args) {
        try {
            ServerSocket ss = new ServerSocket(15180);
            Socket socket = ss.accept();

            //read data from client
            while(true) {
                int data = socket.getInputStream().read();
                System.out.println("Received data!");
            }

        }catch(IOException e) {
            e.printStackTrace();
        }
    }
}

2
听起来远程端没有发送面向行的数据。 - Elliott Frisch
@ElliottFrisch 哇,谢谢。我没想到从控制台接收输入后还需要添加\n - Dioxin
1个回答

9

我想你已经明白了,但是...

readLine()方法返回当前行的其余部分,即所有未使用的字符,直到下一个“行结束”序列或“流结束”,以先到者为准。它会阻塞,等待当前行(根据上述)可用。

因此,如果您的套接字readLine()调用被阻止,则它正在等待远程发送“行结束”标记(例如'\n'),或关闭其套接字输出流(这将在此端导致“流结束”)。

问:为什么从控制台读取时会“工作”?

答:每当您按ENTER键时,控制台都会向流中添加“行结束”序列。(确切添加哪个序列取决于操作系统,但Scanner类将处理所有常见变体以及一些不寻常的变体。)


这里的教训是,只有在输入流是面向行的时才应该使用Scanner.readLine();即,如果编写/生成流的任何内容包含“行结束”标记。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接