Objectoutputstream And Java.io.streamcorruptedexception
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 Socket
s. 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"