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

问题描述 投票:0回答:1

我正在构建一个聊天程序,其中主机通过套接字连接并使用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(),发送原始的,未修改的版本而不是新修改的版本)。

我不能阻止读取,因为在读取时被阻止的进程无法写入其他主机,即使主机无法读取,我也需要能够写入。

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

java java-io blocking objectinputstream
1个回答
0
投票

我弄清楚发生了什么,但我不确定我理解为什么。

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

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

因此,我创建了一个我想要发送的数组的非持久副本,并发送了该副本。当我这样做时,我没有调用重置(仍然不明白为什么)。此外,在从输入流中读取之后,内部有0个字节,因此它永远不会将程序放在readObject将阻塞的位置。

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

无论哪种方式,它现在都按预期工作。

© www.soinside.com 2019 - 2024. All rights reserved.