我正在构建一个聊天程序,其中主机通过套接字连接并使用ObjectInput和ObjectOutput流相互通信。主机从键盘输入构建一个字符串,并将其与一组int一起发送给其他主机。
主机通过readObject()成功读取消息后,while(true)循环继续,并且该主机在下一次调用readObject()时挂起。我只能推测这是因为indata.available()在读取其中的内容后返回true,并且当它在发送其他内容之前尝试再次读取时,它会阻塞(等待)。
下面是相关代码的片段。我做了一些研究,发现我无法刷新或清空输入流。我也无法关闭它 - 由于不断运行的聊天程序的性质,它需要保持开放以继续阅读。
另外,我知道我正在检查indata.available()然后使用inputs.readObject()读取。我认为这是正确的方法,但如果我错了,请纠正我。
我不知道该怎么办!如果我没有将对象写入流,我需要indata.available()返回0。
private InputStream[] indata;
private ObjectInputStream[] inputs;
private ObjectOutputStream[] outputs;
private int[] stamps;
// Establish connections via sockets between 3 hosts, serverless
while (true) {
// Build a message
for (all hosts that aren't myself) {
if ( i != rank ) {
outputs[i].writeObject( message );
outputs[i].writeObject( stamps );
outputs[i].flush( );
outputs[i].reset( );
}
}
// Read a message in from a host that sent one
for (all hosts that aren't myself) {
if (indata[j].available() > 0) {
String message = (String)inputs[j].readObject();
int[] senderStamps = (int[])inputs[j].readObject();
}
}
}
一些其他信息,以澄清:
我正在使用available(),因为教师在他的代码中使用它,我不允许更改它。此外,当只发送一个对象(字符串)时,对available()的调用按预期工作 - 发送端的唯一代码是“writeObject”和“flush”。我的工作是添加代码来发送数组,当我这样做时,我还必须添加代码来重置()ObjectOutputStream(或者我得到其他问题 - 当数组被发送,修改,然后发送再次没有在发送之间调用reset(),发送原始的,未修改的版本而不是新修改的版本)。
我不能阻止读取,因为在读取时被阻止的进程无法写入其他主机,即使主机无法读取,我也需要能够写入。
此外,我们不允许使用多个线程。
我弄清楚发生了什么,但我不确定我理解为什么。
当我在发送之后调用reset(),然后在接收端读取对象时,流中还剩下1个字节。这是导致我陷入if子句然后再次读取时阻塞的原因(因为实际上没有对象可读)。
我不得不调用reset,因为我发送了一个持久对象(数组)。我注意到,当我只发送字符串时,我不必调用reset,字符串和数组之间的区别在于数组是类的数据成员,而每次循环时字符串都是重新创建的跑了。
因此,我创建了一个我想要发送的数组的非持久副本,并发送了该副本。当我这样做时,我没有调用重置(仍然不明白为什么)。此外,在从输入流中读取之后,内部有0个字节,因此它永远不会将程序放在readObject将阻塞的位置。
我想我有点理解为什么我不必在发送非持久对象时重置,但我不明白为什么reset()导致数据留在相应的输入流中。
无论哪种方式,它现在都按预期工作。