java.io.StreamCorruptedException: código de tipo no válido: 00

Básicamente, estoy escribiendo un juego multijugador cliente-servidor. Tengo un SeverCommunicationThread que crea un juego Thread si recibe un RequestForGame crea un juego Thread. Cuando envío una excepción RequestForGame se lanza java.io.StreamCorruptedException: código de tipo no válido: 00 Supongo que es porque ambos hilos intentan leer el mismo ObjectInputStream, no entiendo muy bien cómo funciona, solo sé cómo usarlo eso. ¿Podrías ayudarme a entender cuál es el problema y cómo solucionarlo? Gracias 🙂

public class ServerCommunicationThread extends Thread{ private Socket connectionSocket; private ObjectInputStream inFromClient; private ObjectOutputStream outToClient; private String nickname; private ServerModelManager model; public ServerCommunicationThread(Socket connectionSocket, ServerModelManager model) throws IOException { this.connectionSocket = connectionSocket; inFromClient = new ObjectInputStream(connectionSocket.getInputStream()); outToClient = new ObjectOutputStream(connectionSocket.getOutputStream()); this.model = model; start(); } public void run() { try { String nickname = (String) inFromClient.readObject(); if (model.exists(nickname)){ System.out.println(nickname + " already exists"); outToClient.writeObject(new MessageForClient("Please choose another nickname")); } else { System.out.println(nickname + " connected, adding to list"); model.addClient(nickname, connectionSocket,outToClient,inFromClient); this.nickname=nickname; } while(true){ Object o= inFromClient.readObject();//StreamCorruptedexception if(o instanceof RequestForGame) { RequestForGame r=(RequestForGame)o; String userToPlayWith=r.getUserToPlayWith(); if(userToPlayWith.equals(nickname)) { String message="Playing with yourself makes your palms hairy, choose another opponent"; outToClient.writeObject(message); } else { System.out.println("received request to play with "+userToPlayWith+". starting game"); ClientRepresentative client1=model.getClient(nickname); ClientRepresentative client2=model.getClient(userToPlayWith); ServerGameThread s=new ServerGameThread(client2,client1,client2.getInStream(),client1.getInStream(),client1.getOutStream(),client2.getOutStream()); } } else if(o instanceof String) { String s=(String) o; if(s.equals("i want to quit")) { model.deleteClient(nickname); inFromClient.close(); String q="quit"; outToClient.writeObject(q); connectionSocket.close(); System.out.println(nickname+"has quit without exc"); } } } } catch (EOFException e) { System.out.println(nickname+" has quit"); } catch (SocketException e) { System.out.println(nickname+" has quit"); } catch (Exception e) { e.printStackTrace(); } } } public class ServerGameThread extends Thread { private ClientRepresentative client1,client2; private ObjectInputStream inFromClient1,inFromClient2; private ObjectOutputStream outToClient1,outToClient2; private Field gameField; public ServerGameThread(ClientRepresentative client1, ClientRepresentative client2,ObjectInputStream inFromClient1,ObjectInputStream inFromClient2,ObjectOutputStream outToClient1,ObjectOutputStream outToClient2) { System.out.println("startin game thred"); this.client1=client1;//client 1 goes first this.client2=client2;//client 2 started game this.inFromClient1=inFromClient1; this.inFromClient2=inFromClient2; this.outToClient1=outToClient1; this.outToClient2=outToClient2; gameField=new Field(); System.out.println("check"); start(); } public void run() { System.out.println("Starting game. players: "+client1.getNickname()+";"+client2.getNickname()); try { outToClient1.writeObject(gameField); outToClient2.writeObject(gameField); while(true) { try { System.out.println("listening to "+client1.getNickname()); Object o1=inFromClient1.readObject();//read move from client 1.**//StreamCorruptedexception** while(!(o1 instanceof PlayerMove)) { o1=inFromClient1.readObject();//read move from client 1. } PlayerMove move1=(PlayerMove)o1; System.out.println("received move "+move1+" sending to "+client2.getNickname()); outToClient2.writeObject(move1); System.out.println("listening to "+client2.getNickname()); Object o2=inFromClient2.readObject();//read move from client 1. while(!(o2 instanceof PlayerMove)) { o2=inFromClient2.readObject();//read move from client 1. } PlayerMove move2=(PlayerMove)o2; System.out.println("received move "+move2+" sending to "+client1.getNickname()); outToClient1.writeObject(move2); } catch (ClassNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } 

el método model.addClient aunque no creo que el problema esté aquí

  public void addClient(String nickname, Socket clientSocket,ObjectOutputStream stream,ObjectInputStream inStream) { clients.addClient(nickname, clientSocket,stream,inStream);//add to arraylist //send client list to all clients String[] users=this.getAvailableClients(); ObjectOutputStream[] streams=clients.getOutStreams(); for(int i=0;i<streams.length;i++) { try { streams[i].writeObject(users); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } 

El proxy del lado del cliente que envía objetos al servidor, los métodos se desencadenan mediante acciones del usuario en GUI

  public class Proxy { final int PORT = 1337; String host; String nickname; private Socket clientSocket; private ObjectOutputStream outToServer; private ObjectInputStream inFromServer; private ClientModelManager manager; public Proxy(String nickname,String host,ClientModelManager manager) { this.nickname=nickname; this.host=host; this.manager=manager; this.connect(nickname); } public void connect(String nick) { Socket clientSocket; try { clientSocket = new Socket(host, PORT); System.out.println("client socket created"); outToServer = new ObjectOutputStream(clientSocket.getOutputStream()); inFromServer=new ObjectInputStream(clientSocket.getInputStream()); outToServer.flush(); outToServer.writeObject(nick); ClientReceiverThread t=new ClientReceiverThread(inFromServer,manager); t.start(); } catch (Exception e) { e.printStackTrace(); } } public void makeRequest(String user) { try { outToServer.writeObject(new RequestForGame(user)); } catch(IOException e) { e.printStackTrace(); } } public void quit() { try { outToServer.writeObject(new String("i want to quit")); //clientSocket.close(); } catch (IOException e) { e.printStackTrace(); } } public void sendMove(PlayerMove move) { try { outToServer.writeObject(move); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } 

}

Este problema puede ocurrir si construyes un nuevo ObjectInputStream u ObjectOutputStream sobre el mismo socket en lugar de usar los mismos para la vida del socket; si usa otro tipo de flujo sobre el mismo socket también; o si usa las secuencias de objetos para leer o escribir algo que no es un objeto y se sale de sincronización.

Esto también puede suceder si la JVM que lee el objeto serializado no tiene los archivos jar / clase correctos para el objeto. Esto normalmente da como resultado una ClassNotFoundException , pero si tiene diferentes versiones de jar / class y el serialVersionUID no se modificó entre versiones, se produce una StreamCorruptedException . (Esta excepción también puede ser posible si hay un conflicto de nombre de clase, por ejemplo: un contenedor que contiene una clase diferente con el mismo nombre de clase completo, aunque probablemente también necesiten el mismo serilVersionUID ).

Compruebe que el lado del cliente tenga las versiones correctas de los archivos jar y class.

Hay otra posibilidad de que me encontré con que si implementa una rutina de deserialización personalizada para una clase al agregar este método:

 private void readObject( ObjectInputStream objectInputStream ) throws IOException 

entonces se debe llamar y llamar a objectInputStream.defaultReadObject () antes de cualquier lectura adicional de la stream de entrada para inicializar correctamente el objeto.

Me perdí esto y, a pesar de que el objeto volvía sin que se lanzara una excepción, fue la siguiente lectura del flujo de objetos que generó de manera confusa la excepción de código de tipo no válido.

Este enlace proporciona más información sobre el proceso: http://osdir.com/ml/java.sun.jini/2003-10/msg00204.html .

Si ObjectInputStream se construye solo una vez y luego pasa una referencia de la misma al otro subproceso, simplemente encierre el acceso de este objeto dentro del bloque synchronized para asegurarse de que solo un subproceso puede acceder a este objeto a la vez.

Siempre que esté leyendo desde ObjectInputStream solo acceda al mismo dentro del bloque synchronized si se comparte entre varios hilos.


Código de muestra: (hazlo para todas las ocurrencias de readObject() )

 ... String nickname = null; synchronized (inFromClient) { nickname = (String) inFromClient.readObject(); } 

Yo también tuve esta excepción. Ocurrió porque utilicé dos subprocesos para la clase Servidor y la clase Cliente. Usé un hilo para enviar y recibir objetos. Entonces estuvo bien. Esta es una forma fácil de resolver el problema si no está familiarizado con la synchronized .

java.io.StreamCorruptedException: código de tipo no válido: 00

Recientemente me encontré con este problema, sin hacer lo que OP hizo. Realicé una búsqueda rápida en Google y no encontré nada que fuera demasiado útil y porque creo que lo resolví. Estoy haciendo un comentario con mi solución.

TLDR: no tiene varios hilos que escriban en la misma secuencia de salida al mismo tiempo (sino que se turnan). Causará problemas cuando el lado del cliente intente leer los datos. La solución es bloquear la escritura en la salida.

Estoy haciendo algo muy similar a OP, haciendo un juego multijugador (modelo cliente-servidor). Tengo un hilo como OP que está escuchando el tráfico. Lo que estaba sucediendo, en mi lado del servidor era que el servidor tenía varios hilos que estaban escribiendo en la transmisión de un cliente al mismo tiempo (no creía que fuera posible, el juego era base de media vuelta). El hilo del lado del cliente que estaba leyendo el tráfico entrante lanzaba esta excepción. Para resolver esto básicamente puse un candado en la parte que escribió en la secuencia del cliente (en el lado del servidor) para que cada subproceso en el lado del servidor tuviera que obtener el locking antes de escribir en la secuencia.