在我发布这篇文章之前,我查看过一些关于此例外的问题,但找不到确切的答案。
我有一个客户端服务器应用程序,它基本上是一个与TCP连接的套接字程序。 在运行正常一段时间之后,我从客户端获得了这个例外。但是,即使它抛出异常,客户端也会向服务器发送数据。(可能是因为Event对象连续传递)。但是服务器在接收数据时工作正常。我在发送数据时从客户端获得的异常是
java.io.IOException: stream active
..这发生在下面代码中提到的“LINE 01”中。
这是我使用的客户端代码。
// And "Event" objects are passed continuously to this method one by one.
SocketChannel socketChannel = null;
try {
socketChannel = SocketChannel.open(new InetSocketAddress(host, port));
oos = new ObjectOutputStream(socketChannel.socket().getOutputStream());
oos.reset(); -----------> LINE 01
oos.writeObject(event);
} catch (IOException e) {
throw new RuntimeException(e);
}
这是服务器代码
ServerSocketChannel serverSocketChannel = null;
try {
serverSocketChannel = ServerSocketChannel.open();
serverSocketChannel.socket().bind(new InetSocketAddress(port));
SocketChannel socket = serverSocketChannel.accept();
ObjectInputStream ois = new ObjectInputStream(socket.socket().getInputStream());
do {
Object object = ois.readObject();
if(object instanceof Event) {
Event event = (Event)object ;
viewDetailsInUI(event);
}
} while (true);
这是我从客户端获得的堆栈跟踪。
java.io.IOException: stream active
at java.io.ObjectOutputStream.reset(ObjectOutputStream.java:478)
at org.demo.siddhi.server.EventSenderClient.sendEventToSubscriber(EventSenderClient.java:42)
at org.demo.siddhi.server.query.types.SimpleStockQuoteVWAPQueryProvider$3.callBack(SimpleStockQuoteVWAPQueryProvider.java:344)
at org.siddhi.core.OutputStreamHandler.run(OutputStreamHandler.java:61)
at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
at java.lang.Thread.run(Thread.java:662)
任何人都可以解释为什么会这样?
答案 0 :(得分:4)
这里有几个问题。
正如Peter Lawrey指出的那样,立即调用reset()构建ObjectOutputStream是完全没有意义的,而且可能是非法的。删除它。
您正在通过流在阻止模式下使用SocketChannel,即您在两种情况下都只使用底层套接字。使用Socket
和ServerSocket
会更好。它更简单,更清晰。
您的服务器循环读取多个对象的ObjectInputStream,但您的客户端创建一个新连接,发送一个对象,然后(我希望)关闭它。这些不加起来。 要么你的客户端应该保存TCP连接和ObjectOutputStream并使用它来编写多个对象,在这种情况下你可能需要在 writeObject()之后调用reset(),并且当服务器获得EOFException时,服务器需要突破循环,或服务器可以在读取一个对象后关闭其连接,并且不需要while(true)循环。
答案 1 :(得分:3)
它似乎相信它已经在序列化一个对象。
IOException如果在序列化对象时调用reset()。
您无需在开始时调用reset(),因为没有任何重置()。我会放弃它,它可能会正常工作。
如果要定期调用reset,可以在writeObject()之后调用它。
当缓冲流时,你也应该在某处调用flush()。
答案 2 :(得分:1)
查看OOS代码:
493 if (depth != 0) {
494 throw new IOException("stream active");
495 }