Java InputStream.available()在读取后返回> 0

时间:2019-04-18 05:03:22

标签: java java-io blocking objectinputstream

我正在构建一个聊天程序,其中主机通过套接字连接,并使用ObjectInput和ObjectOutput流彼此对话。主机通过键盘输入构建字符串,并将其与整数数组一起发送给其他主机。

主机成功通过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”。添加代码以发送数组是我的工作,当我这样做时,我还必须添加代码以reset()ObjectOutputStream(否则我会遇到其他问题-在发送,修改并发送数组时再次在发送之间不调用reset()的情况下,将发送未修改的原始版本,而不是新修改的版本。

我不能只是在读取时阻塞,因为在读取时阻塞的进程无法写入其他主机,因此即使主机没有任何内容,我也必须能够写入。

此外,我们不允许使用多个线程。

1 个答案:

答案 0 :(得分:0)

我知道发生了什么,但是我不确定为什么。

当我在发送后调用reset(),然后在接收端读取对象时,流中还剩下1个字节。这就是导致我陷入if子句中,然后在再次读取时阻塞的原因(因为实际上没有要读取的对象)。

我必须调用reset,因为我正在发送一个持久对象(数组)。我注意到当我只发送字符串时,我不必调用reset,而字符串和数组之间的区别在于,每次循环时都重新创建字符串时,数组是该类的数据成员。跑了。

因此,我创建了要发送的阵列的非持久副本,并发送了该副本。当我这样做时,我不必打电话给reset(仍然不明白为什么)。此外,从输入流读取后,内部还剩下0个字节,因此它永远不会将程序置于readObject会阻塞的位置。

我想我有点理解为什么发送非持久对象时不必重置,但是我不明白为什么reset()导致数据保留在相应的输入流中。

无论哪种方式,它现在都可以正常工作。