2011-07-23 8 views
9

Mam architekturę serwer-klient, w której klient wysyła XML do serwera, który odczytuje go i generuje z niego plik PDF i odsyła go do klienta.Odsłonięcie gniazda wejściowego w gniazdku zamyka gniazdko?

Po stronie klienta:

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

Tymczasem po stronie serwera:

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 

Jeśli nie wycofać klienta InputStream (po stronie serwera) i po prostu odesłać manekina PDF to wszystko idzie gładko. Tak więc, muszę założyć, że Unmarshaller zamyka podany InputStream, tym samym niejawnie zamykając klienta Socket rujnując mój dzień ...

Czy masz pomysł na rozwiązanie tego problemu?

Odpowiedz

7

Wywołania klasy XMLEntityManager są zamykane w obiekcie InputStream.

Można użyć wartości FilterInputStream, aby uniknąć wywołania metody close() z podstawowego strumienia.

Podklasa FilterInputStream i zastąpić metodę Close() z pustym korpusem:

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

    @Override 
    public void close() { 
    // do nothing 
    } 
} 

następnie zmienić swoje wycofać() Wezwanie do

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

Więc ramy JAXB nadal wywołuje close() na strumień, ale teraz jest odfiltrowywany przez twoją własną instancję strumienia, a strumień gniazda pozostaje otwarty.

+0

Dziękujemy, Twój rozwiązanie działa jak urok! :) –

6

Jeśli nie chcesz jawnie zastąpić InputStream w kodzie jak vanje sugerują, Apache commons-io zapewnić realizację że współpracy to:

przyjrzeć się:

CloseShieldInputStream

+0

Bardzo dobre rozwiązanie –