Skip to content Skip to sidebar Skip to footer

Objectoutputstream And Java.io.streamcorruptedexception

When I try to send a customobject (See Content.java) from my client to the server with ObjectOutputStream, I get StreamCorruptedException after the first object is sent. So if I tr

Solution 1:

EDIT: I've added an array in the receiver to close all streams when the receiver stops.

You should redesign your protocol layer. In both devices you have to create a ServerSocket to listen for new Sockets. Obviously, if you call any read() method the current thread will enter in a blocked state, so you need to use a secondary thread. You need to start() and stop() the receiver and use a listener to notify the socket creations. A possible implementation (it can be improved a lot, but the core is this):

Receiver.java

publicclassReceiver{
private ArrayList<SocketStream> socketStreams;
    private OnNewSocketListener listener;
    private ServerSocket server;
    private Thread thread;
    privateint port;

    publicstaticinterfaceOnNewSocketListener{
        voidonNewSocket (Stream stream);
    }

    publicReceiver (int port, OnNewSocketListener listener){
        this.listener = listener;
            this.port = port;
    }

    public synchronized start (){
        if (thread != null) return;

        server = new ServerSocket (port);
        thread = new Thread (new Runnable (){
                @Override
                publicvoidrun (){
                    try{
                        running = true;
                        while (running){
                        socketStreams.add (stream);
                                                    //See Stream.java below
                            listener.onNewSocket (new Stream (server.accept ()));
                        }
                    }catch (SocketException e){
                        //stop() has been called
                    }catch (IOException e){
                        //Error handling
                    }
                }
            }).start ();
        }
    }

    public synchronized voidstop (){
        if (thread == null) return;

        running = false;
        try{
            if (server != null){
                server.close ();
            }
        }catch (IOException e){}

    for (SocketStream stream: socketStreams){
        stream.close ();
    }
    socketStreams.clear ();

        thread = null;
    }
}

Then you need another class that starts a thread when you want to read and write to this socket. To read you need another thread. You also need another listener to notify the object read and to notify when the other device closes the stream. You need a startReading() and close() methods (if you stop reading the socket it will close):

Stream.java

publicclassStream{
    private Socket socket;
    private OnCloseStreamListener closeListener;
    private OnReadObjectListener readListener;
    private ObjectInputStream in;
    private ObjectOutputStream out;
    private Thread thread;

    publicstaticinterfaceOnReadObjectListener{
        voidonReadObject (Object obj);
    }

    publicstaticinterfaceOnCloseStreamListener{
        voidonCloseStream ();
    }

    //Used by the receiver to create an input socketpublicStream (Socket socket){
        this.socket = socket;
        out = new ObjectOutputStream (socket.getOutputStream ());
    }

    //Used by the user to create an output socket, when the client wants to create a socket with the serverpublicStream (String address, int port){
        socket = new Socket (address, port);
        out = new ObjectOutputStream (socket.getOutputStream ());
    }

    publicvoidsetOnCloseStreamListener (OnCloseStreamListener listener){
        closeListener = listener;
    }

    publicvoidsetOnReadObjectListener (OnReadObjectListener listener){
        readListener = listener;
    }

    public synchronized voidstartReading (){
        if (thread != null) return;

        thread = new Thread (new Runnable (){
            @Override
            publicvoidrun (){
                try{
                    in = new ObjectInputStream (socket.getInputStream ());
                    reading = true;
                    while (reading){
                        Object obj = in.readObject ();
                        if (obj == null){
                            //The other device has closed its socket stream
                            reading = false;
                            closeListener.onCloseSocketStream ();
                        }else{
                            readListener.onReadObject (obj);
                        }
                    }
                }catch (SocketException e){
                    //stopReading() has been called
                }catch (IOException e){
                    //Error handling
                }
            }
        }).start ();
    }

    public synchronized voidwriteObject (Object obj){
        out.writeObject (obj);
        out.flush;
    }

    public synchronized voidclose (){
        if (thread != null){
            reading = false;
            socket.close ();
            in.close ();
            out.close ();
            thread = null;
        }else{
            socket.close ();
            in.close ();
        }
    }
}

Usage: Server

Receiverreceiver=newReceiver (5000, newReceiver.OnNewSocketListener (){
    @OverridevoidonNewSocket(Stream stream){
        stream.setOnCloseStreamListener (newStream.OnCloseStreamListener (){
            @OverridevoidonCloseStream(){
                //Stream is closed automatically, don't need to call close()//Do something
            }
        });
        stream.setOnReadObjectListener (newStream.OnReadObjectListener (){
            @OverridevoidonReadObject(Object obj){
                //Do something with objif (obj.isDoingSomeMaliciousActivities ()){
                    stream.close ();
                }elseif (obj.isDoingGoodStuff){
                                    stream.writeObject (newGoodStuff ());
                            }
            }
        });
        stream.startReading ();
    }
});
receiver.start ();
Thread.sleep (10000);
receiver.stop ();

Client

Streamstream=newStream ("localhost", 5000);
stream.setOnCloseStreamListener (newStream.OnCloseStreamListener (){
    @OverridevoidonCloseStream(){
        //Stream is closed automatically, don't need to call close()//Do something
    }
});
stream.setOnReadObjectListener (newStream.OnReadObjectListener (){
    @OverridevoidonReadObject(Object obj){
        //Do something with objif (obj.isDoingSomeMaliciousActivities ()){
            stream.close ();
        }elseif (obj.isDoingGoodStuff){
            stream.writeObject (newGoodStuff ());
        }
    }
});
stream.startReading ();
if (iHaveAGoodDay){
    stream.writeObject (newIamHappy ());
}else{
    stream.writeObject (newIwillHackYou ());
}
Thread.sleep (10000);
stream.close ();

This code is the core of the socket layer. It won't work because I don't tested it. You first need to understand the code to proceed with the protocol. Note: Don't be afraid to use all the listeners you think you need because you are constructing a layer that notifies events. It's like the user interaction when presses a button but with sockets.

Post a Comment for "Objectoutputstream And Java.io.streamcorruptedexception"