解组Socket的InputStream会关闭Socket吗?

Koh*_*ert 9 java sockets jaxb xml-serialization jaxb2

我有一个服务器 - 客户端架构,客户端将XML发送到读取它的服务器并从中生成PDF并将其发送回客户端.

在客户端:

JAXBElement<Xml> xml = ...
Socket sock = ...
Marshaller marshaller = ...
marshaller.marshal(xml, sock.getOutputStream());
sock.shutdownOuput();    
Run Code Online (Sandbox Code Playgroud)

同时在服务器端:

ServerSocket server = ...
Socket client = server.accept();
Unmarshaller unmarshaller = ...
// client.isClosed() -> false
JAXBElement<Xml> xml =
  (JAXBElement<Xml>)) unmarshaller.unmarshall(client.getInputStream());
// client.isClosed() -> true
Pdf pdf = new Pdf(xml);
client.getOutputStream().write(pdf.toBytes());
// "socket is closed" IOException is thrown
Run Code Online (Sandbox Code Playgroud)

如果我不解组客户端InputStream(在服务器端)并只发送一个虚拟PDF,那么一切都顺利进行.所以,我必须假设Unmarshaller关闭了InputStream它,因此暗中关闭客户Socket毁了我的一天......

解决这个问题的任何想法?

van*_*nje 8

XMLEntityManager类在InputStream上调用close.

您可以使用FilterInputStream来避免对基础流进行close()调用.

子类FilterInputStream并使用空体覆盖close()方法:

public class MyInputStream extends FilterInputStream {
  public MyInputStream(InputStream in) {
    super(in);
  }

  @Override 
  public void close() {
    // do nothing
  }
}
Run Code Online (Sandbox Code Playgroud)

然后将你的unmarshall()调用更改为

JAXBElement<Xml> xml =
    (JAXBElement<Xml>)) unmarshaller.unmarshall(new MyInputStream(client.getInputStream()));
Run Code Online (Sandbox Code Playgroud)

所以JAXB框架仍然在流上调用close(),但它现在由您自己的流实例过滤掉,并且套接字流保持打开状态.


Chu*_*Mah 7

如果您不想像vanje建议那样显式覆盖代码中的InputStream,那么Apache commons-io提供了一个实现此功能的实现:

看一眼 :

CloseShieldInputStream