从 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() 块的主要内容,如果未能解决你的问题,请参考以下文章
Java -- 如何从 inputStream (socket/socketServer) 中读取未知数量的字节?