套接字缓冲读取器从来没有准备好
只是为了完全透明,这是一个任务。套接字缓冲读取器从来没有准备好
还有更多的事情要做,但在那一刻,我只是想获得以下内容:
- 节点A从文本文件
- 节点发送的文本文件读取(减去第一线)使用套接字
- 节点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上看到的其他一些例子。
谢谢你的任何和所有帮助。我对套接字,端口,聆听和其他方面非常陌生,所以如果我一开始不明白你的建议,请原谅我。我会尽我所能去理解它。
我没有添加整个代码,希望能够使问题更具可读性和清晰度,但如果您需要更多信息,请随时提问,我会尽我所能提供。
服务器必须先从ServerSocket的Socket中获取到客户端。
connectionSocket = mySocket.accept();
服务器线程将休眠,直到客户端导致它接受connectionSocket。
然后你可以从connectionSocket中读取。 ready
不需要。
由于这是一项任务,我将其余的给你。
顺便说一个典型的服务器会做:
for (;;) {
Socket socket = serverSocket.accept();
... pass the socket to a thread from a pool of threads
}
感谢您的回应,但有几件事仍然令人困惑。一旦服务器完成等待并且客户端已连接,我不需要再执行.accept(),对吧?我试图更改我的代码,以便只有最初的.accept,但我似乎仍然无法从套接字读取,它只是永远挂在readLine()上。 –
您应该只有一个'ServerSocket.accept'产生一个Socket读取。 –
谢谢。我更新了代码,删除了额外的.accepts(),删除了.ready(),现在显示了挂起的位置。 –
我认为问题是,准备只是意味着,如果调用读,也不会封锁。你可以看到,被执行的代码,如果你查找功能上grepcode:
就绪的线程只是意味着它不会阻止,这是非常有用的,当你想确保你的线程ISN”不会被束缚,但并不真正告诉你你是否有缓冲区。
你想要做的是执行readline,作为阻塞调用,直到数据被消耗。如果你不想阻塞你当前的线程,那么分离出一个新的消费线程,这个消息线程可以被阻塞。
此外,请确保您使用封闭的套接字或flush来结束您的发送通信,以在消耗流完成时指示消耗流。而且你只需要在每个打开/关闭会话中接受一次套接字。
我不介意阅读阻止我当前的线程,这应该不是一个问题。我试着改变我的代码,最初只有一个.accept(),并改变in.ready(),以确保从readLine()返回的行不是null(有更多的行要移动来读入),但它仍然挂在最初的readLine()我试图做的。 –
Readline需要结束字符串,它正在寻找\ n EOL或关闭的套接字。如果它挂起,这意味着它正在等待更多数据。您可以在写作结束时关闭写入器上的套接字作为测试以确认。 – user1442498
谢谢。我测试了一个mySocket.close();在节点A的代码末尾。虽然没有运气。我还需要在另一端关闭它吗? –
1)每次'ServerSocket.accept()'返回时,您都会在服务器和客户端之间建立连接的套接字。 * *表示*连接*不*再次调用'ServerSocket.accept()'。 2)在您的客户端中,PrintWriter在内部缓冲数据。如果你想调用'out.print(line);'的结果立即在网络上看到,那么你必须调用'out.flush()'作为下一条语句。 –
所有'ready()'都会返回是否下一次读取会立即返回。请参阅[文档](https://docs.oracle.com/javase/9/docs/api/java/io/Reader.html#ready--)。 – VGR