【问题标题】:Unmarshalling a Socket's InputStream closes the Socket?解组 Socket 的 InputStream 会关闭 Socket?
【发布时间】:2011-10-11 14:22:29
【问题描述】:

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

在客户端:

JAXBElement<Xml> xml = ...
Socket sock = ...
Marshaller marshaller = ...
marshaller.marshal(xml, sock.getOutputStream());
sock.shutdownOuput();    

同时在服务器端:

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

如果我不解组客户端的InputStream(在服务器端),而只是发回一个虚拟 PDF,那么一切都会顺利进行。所以,我必须假设Unmarshaller 关闭了它给出的InputStream,因此隐式关闭客户端Socket 毁了我的一天......

有解决这个问题的想法吗?

【问题讨论】:

    标签: java sockets xml-serialization jaxb jaxb2


    【解决方案1】:

    如果您不想像 vanje 建议的那样在您的代码中显式覆盖 InputStream,Apache commons-io 提供实现此目的的实现:

    看看:

    CloseShieldInputStream

    【讨论】:

      【解决方案2】:

      类 XMLEntityManager 在 InputStream 上调用 close。

      您可以使用FilterInputStream 来避免底层流的 close() 调用。

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

      public class MyInputStream extends FilterInputStream {
        public MyInputStream(InputStream in) {
          super(in);
        }
      
        @Override 
        public void close() {
          // do nothing
        }
      }
      

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

      JAXBElement<Xml> xml =
          (JAXBElement<Xml>)) unmarshaller.unmarshall(new MyInputStream(client.getInputStream()));
      

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

      【讨论】:

        猜你喜欢
        • 2011-02-19
        • 2021-06-12
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-07-15
        • 2012-01-15
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多