套接字缓冲读取器从来没有准备好

套接字缓冲读取器从来没有准备好

问题描述:

只是为了完全透明,这是一个任务。套接字缓冲读取器从来没有准备好

还有更多的事情要做,但在那一刻,我只是想获得以下内容:

  1. 节点A从文本文件
  2. 节点发送的文本文件读取(减去第一线)使用套接字
  3. 节点B从所述插座读取到节点B,并打印到控制台

然而,现在,它似乎并不会发送任何信息,或它没有被正确读取ctly由节点B.

在我的主类,我设置了这样的节点:

NodeA nodeA = new NodeA(); 
NodeB nodeB = new NodeB(); 

new Thread(nodeA).start(); 
new Thread(nodeB).start(); 

在节点A,我这样做:

//Open a socket for talking with NodeB 
Socket mySocket = new Socket(InetAddress.getLocalHost(), portNum); 

//Set up the socket's output 
PrintWriter out = new PrintWriter(mySocket.getOutputStream(), true); 

//Loop through the lines of the confA file, writing them to the socket 
String line = bufferedReader.readLine(); 
while (line != null) 
{ 
    //Write the line to the socket, get the next line 
    out.println(line); //updated to println, this flushes and fixes another problem 
    out.flush(); 
    line = bufferedReader.readLine(); 
} 

//Close the socket 
mySocket.close(); 

注意,节点A的循环作品精细。它不会永远循环,当我用打印语句进行测试时,它会经历预定的文本行。

然后,在节点B的结束:更新,以显示当前节点B的代码

//Open the socket 
ServerSocket mySocket = new ServerSocket(portNum); 
Socket connectionSocket = mySocket.accept(); 

//Set up a reader on the socket to get what's coming from it 
BufferedReader in = new BufferedReader(new InputStreamReader(connectionSocket.getInputStream())); 

String line = in.readLine(); //hang occurs here 

while(line != null) { 
    System.out.println(line); 
    line = in.readLine();; 
} 

然而,in.ready()是不正确的。我已经尝试过等待使用while循环发生,但它永远不会发生。

我真的不知道为什么。我不知道我是否正确设置了套接字,是否正确设置了服务器,是否正确收听,等等。

我刚才发现让B成为一个服务器,它正在监听A,这是最有意义的。我希望这是正确的。它看起来类似于我在SO上看到的其他一些例子。

谢谢你的任何和所有帮助。我对套接字,端口,聆听和其他方面非常陌生,所以如果我一开始不明白你的建议,请原谅我。我会尽我所能去理解它。

我没有添加整个代码,希望能够使问题更具可读性和清晰度,但如果您需要更多信息,请随时提问,我会尽我所能提供。

+0

1)每次'ServerSocket.accept()'返回时,您都会在服务器和客户端之间建立连接的套接字。 * *表示*连接*不*再次调用'ServerSocket.accept()'。 2)在您的客户端中,PrintWriter在内部缓冲数据。如果你想调用'out.print(line);'的结果立即在网络上看到,那么你必须调用'out.flush()'作为下一条语句。 –

+0

所有'ready()'都会返回是否下一次读取会立即返回。请参阅[文档](https://docs.oracle.com/javase/9​​/docs/api/java/io/Reader.html#ready--)。 – VGR

服务器必须先从ServerSocket的Socket中获取到客户端。

connectionSocket = mySocket.accept(); 

服务器线程将休眠,直到客户端导致它接受connectionSocket。

然后你可以从connectionSocket中读取。 ready不需要。

由于这是一项任务,我将其余的给你。


顺便说一个典型的服务器会做:

for (;;) { 
    Socket socket = serverSocket.accept(); 
    ... pass the socket to a thread from a pool of threads 
} 
+0

感谢您的回应,但有几件事仍然令人困惑。一旦服务器完成等待并且客户端已连接,我不需要再执行.accept(),对吧?我试图更改我的代码,以便只有最初的.accept,但我似乎仍然无法从套接字读取,它只是永远挂在readLine()上。 –

+1

您应该只有一个'ServerSocket.accept'产生一个Socket读取。 –

+0

谢谢。我更新了代码,删除了额外的.accepts(),删除了.ready(),现在显示了挂起的位置。 –

我认为问题是,准备只是意味着,如果调用读,也不会封锁。你可以看到,被执行的代码,如果你查找功能上grepcode:

http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/7u40-b43/java/io/BufferedReader.java#BufferedReader.ready%28%29

就绪的线程只是意味着它不会阻止,这是非常有用的,当你想确保你的线程ISN”不会被束缚,但并不真正告诉你你是否有缓冲区。

你想要做的是执行readline,作为阻塞调用,直到数据被消耗。如果你不想阻塞你当前的线程,那么分离出一个新的消费线程,这个消息线程可以被阻塞。

此外,请确保您使用封闭的套接字或flush来结束您的发送通信,以在消耗流完成时指示消耗流。而且你只需要在每个打开/关闭会话中接受一次套接字。

+0

我不介意阅读阻止我当前的线程,这应该不是一个问题。我试着改变我的代码,最初只有一个.accept(),并改变in.ready(),以确保从readLine()返回的行不是null(有更多的行要移动来读入),但它仍然挂在最初的readLine()我试图做的。 –

+0

Readline需要结束字符串,它正在寻找\ n EOL或关闭的套接字。如果它挂起,这意味着它正在等待更多数据。您可以在写作结束时关闭写入器上的套接字作为测试以确认。 – user1442498

+0

谢谢。我测试了一个mySocket.close();在节点A的代码末尾。虽然没有运气。我还需要在另一端关闭它吗? –