Java 套接字的缓冲读取器从未就绪
为了完全透明,这是一项任务 还有很多事情要做,但目前我只是想做以下几点:Java 套接字的缓冲读取器从未就绪,java,sockets,bufferedreader,java-threads,Java,Sockets,Bufferedreader,Java Threads,为了完全透明,这是一项任务 还有很多事情要做,但目前我只是想做以下几点: 节点A从文本文件读入 节点A使用套接字将文本文件(减去第一行)发送给节点B 节点B从所述套接字读入,并将其打印到控制台 然而,现在,要么信息没有被发送,要么节点B没有正确读取 在我的主类中,我设置了如下节点: NodeA nodeA = new NodeA(); NodeB nodeB = new NodeB(); new Thread(nodeA).start(); new Thread(nodeB).start();
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的服务器是最有意义的。我希望这是对的。它看起来和我在网上看到的其他一些例子很相似
谢谢你的帮助。我对套接字、端口、侦听和其他方面非常不熟悉,所以如果我一开始不理解您的建议,请原谅我。我会尽力去理解它
我没有添加整个代码,希望能让它更具可读性,更清楚问题所在,但如果您需要更多信息,请随时询问,我会尽力提供。服务器必须首先从服务器套接字获取套接字,然后将套接字发送到客户端
connectionSocket = mySocket.accept();
服务器线程将处于休眠状态,直到客户端使其接受connectionSocket
然后可以从connectionSocket中读取<代码>就绪不需要
由于这是一项任务,剩下的就交给你了
顺便说一句,一台典型的服务器可以做到:
for (;;) {
Socket socket = serverSocket.accept();
... pass the socket to a thread from a pool of threads
}
服务器必须首先从服务器套接字获取套接字到客户端
connectionSocket = mySocket.accept();
服务器线程将处于休眠状态,直到客户端使其接受connectionSocket
然后可以从connectionSocket中读取<代码>就绪不需要
由于这是一项任务,剩下的就交给你了
顺便说一句,一台典型的服务器可以做到:
for (;;) {
Socket socket = serverSocket.accept();
... pass the socket to a thread from a pool of threads
}
我认为问题在于ready仅仅意味着如果你调用read,它不会阻塞。如果在grepcode上查找函数,可以看到执行的代码: 一个就绪线程只是意味着它不会阻塞,当你想确保你的线程不会被阻塞时,这是很有用的,但并不能真正告诉你是否有缓冲区 您要做的是执行readline,作为阻塞调用,直到数据被消耗为止。如果你不想让它阻塞你当前的线程,那么就为这个读到的线程派生一个新的消费者线程,它可以阻塞
此外,请确保您正在使用关闭的套接字或刷新来结束发送通信,以指示消费流何时完成。每个打开/关闭会话只需要接受一次套接字。我认为问题在于就绪只意味着如果调用read,它不会阻塞。如果在grepcode上查找函数,可以看到执行的代码: 一个就绪线程只是意味着它不会阻塞,当你想确保你的线程不会被阻塞时,这是很有用的,但并不能真正告诉你是否有缓冲区 您要做的是执行readline,作为阻塞调用,直到数据被消耗为止。如果你不想让它阻塞你当前的线程,那么就为这个读到的线程派生一个新的消费者线程,它可以阻塞
此外,请确保您正在使用关闭的套接字或刷新来结束发送通信,以指示消费流何时完成。每个打开/关闭会话只需接受一次套接字。感谢您的回复,但有几件事仍然让人感到困惑。一旦服务器完成等待并且客户端连接,我就不需要再执行另一个.accept(),对吗?我试图更改我的代码,以便只使用首字母。accept,但我似乎仍然无法从套接字读取,它只是永远挂在readLine()上。您应该只有一个
ServerSocket。accept
生成一个可从中读取的套接字。谢谢。我已经更新了代码,删除了额外的.accepts()和.ready(),现在显示了挂起发生的位置。好的,您已经看到了。在客户端执行println
而不是print
。这会将缓冲区刷新到输出。一个新的PrintWriter(…,true)
会在println上自动刷新。在我身边晚安,谢谢!它现在似乎工作得很好。我想知道为什么在我尝试时,结果会变成一行。flush()。现在我可以把它删除了。谢谢你的回复,但是有一些事情仍然让人很困惑。一旦服务器完成等待并且客户端连接,我就不需要再执行另一个.accept(),对吗?我试图更改我的代码,以便只使用首字母。accept,但我似乎仍然无法从套接字读取,它只是永远挂在readLine()上。您应该只有一个ServerSocket。accept
生成一个可从中读取的套接字。谢谢。我已经更新了代码,删除了额外的.accepts()和.ready(),现在显示了挂起发生的位置。好的,您已经看到了。在客户端执行println
而不是print
。这会将缓冲区刷新到输出。一个新的PrintWriter(…,true)
会在println上自动刷新。在我身边晚安,谢谢!它现在似乎工作得很好。我习惯了