繁体   English   中英

从Socket使用InputStream时,Scanner.nextLine()会阻塞

[英]Scanner.nextLine() blocks when using InputStream from Socket

当我直接使用Socket.getInputStream()接收数据时(没有像Scanner这样的某种接口),它不会阻塞。 但是,当我尝试使用扫描仪时(类似于我们从System.in接收字符串的方式),它确实如此。 我想知道这个的原因,以及连接的Socket提供给你的InputStream inSystemInputStream 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();
        }
    }
}

(我想你已经想到了这个但是...)

readLine()方法返回当前行的其余部分。 也就是说,所有未消耗的字符直到下一个“行尾”序列,或者“流的结束”,它始终是第一个。 它将阻塞,等待当前行(根据上述)可用。

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

问:当你从控制台读取时,为什么它“起作用”?

答:无论何时按Enter键,控制台都会向流添加“行尾”序列。 (确切地说,添加的序列是依赖于操作系统的,但Scanner类将处理所有常见的变种,以及一些不寻常的变种。)


这里的教训是,如果输入流是面向行的,你应该只使用Scanner.readLine() ; 即如果写入/生成的流包括“行尾”标记。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM