【发布时间】:2019-04-18 05:03:21
【问题描述】:
我正在构建一个聊天程序,其中主机通过套接字连接并使用 ObjectInput 和 ObjectOutput 流相互交谈。主机根据键盘输入构建一个字符串,并将其与整数数组一起发送给其他主机。
主机通过 readObject() 成功读取消息后,while(true) 循环继续,并且该主机在下一次调用 readObject() 时挂起。我只能推测这是因为 indata.available() 即使在读取了其中的内容之后也会返回 true,并且当它在发送其他内容之前尝试再次读取时,它会阻塞(等待)。
相关代码的sn-p如下。我做了一些研究,发现我无法刷新或清空输入流。我也无法关闭它 - 由于持续运行的聊天程序的性质,它需要保持打开状态才能继续阅读。
另外,我知道我正在检查 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”。添加代码以发送数组是我的工作,当我这样做时,我还必须添加代码以 reset() ObjectOutputStream(或者我遇到其他问题 - 发送、修改和发送数组时再次在发送之间不调用 reset(),则发送原始的、未修改的版本而不是新修改的版本)。
我不能只阻塞读取,因为读取阻塞的进程无法写入其他主机,即使主机没有可读取的内容,我也需要能够写入。
另外,我们不允许使用多个线程。
【问题讨论】:
-
InputStream::available总是返回0。这个方法的javadocs说'这个方法应该被子类覆盖'。那么你能发布一个真正实现的indata吗?此外,您从inputs读取数据。你能发布indata和inputs的关系吗? -
我想知道你是否可以做一个 (str = inputs[j].readObject()) != null) 作为你的检查
-
@AnarAmrastanov 它是被 OP 已经在使用的子类覆盖,例如
ObjectInputStream。阅读问题。 -
这里唯一的问题是您使用的是
available()。简单的回答:不要。这种方法的正确用法很少(如果有的话),这不是其中之一。 一些 字节可用这一事实永远不能保证整个对象 可用,因此您将总是冒着被readObject()阻塞的风险。所以就这样做吧。堵塞。为每个套接字指定一个线程。 -
@Benson99 不,他不能。当整个对象不可用时,
readObject()不会返回null。请参阅 Javadoc。
标签: java java-io blocking objectinputstream