从 Socket 使用 InputStream 时的 Scanner.nextLine() 块

Posted

技术标签:

【中文标题】从 Socket 使用 InputStream 时的 Scanner.nextLine() 块【英文标题】:Scanner.nextLine() blocks when using InputStream from Socket 【发布时间】:2014-09-10 19:15:50 【问题描述】:

当我直接使用Socket.getInputStream() 接收数据时(没有像 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();
        
    

【问题讨论】:

听起来远程端没有发送面向线路的数据。 @ElliottFrisch 哇,谢谢。我认为在收到来自控制台的输入后我不必添加\n 【参考方案1】:

(我想你已经想通了,但是……)

readLine() 方法返回当前行的其余部分。也就是说,直到下一个“行尾”序列或“流尾”的所有未使用的字符,以先出现的为准。它将阻塞,等待当前行(根据上述)可用。

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

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

答:只要您按 ENTER,控制台就会向流中添加一个“行尾”序列。 (具体添加的序列取决于操作系统,但Scanner 类将处理所有常见的变体,以及一些不寻常的变体。)


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

【讨论】:

以上是关于从 Socket 使用 InputStream 时的 Scanner.nextLine() 块的主要内容,如果未能解决你的问题,请参考以下文章

从 socket 和 inputStream 读取缓慢

Java -- 如何从 inputStream (socket/socketServer) 中读取未知数量的字节?

取消从 InputStream 读取

读取 NANOHTTPD 的 InputStream 会产生 Socket TimeOut 异常

关于InputStream类的available()方法

InputStream类的available()方法