java.io.StreamCorruptedException:类型代码无效:00

所以基本上我正在写一个客户端 – 服务器多人游戏。 我有一个SeverCommunicationThread,如果他收到RequestForGame就会创建一个gameThread来创建gameThread。 当我发送一个RequestForGameexception时抛出java.io.StreamCorruptedException:无效的类型代码:00我假设它是因为两个线程都试图读取相同的ObjectInputStream,我对它的工作方式我不太了解,我只知道如何使用它。 你能帮我理解问题是什么以及如何解决? 谢谢 :)

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(); } } } 

虽然我认为问题不在这里,但是model.addClient方法

  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(); } } } 

将对象发送到服务器的客户端代理,这些方法由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(); } } 

}

如果您在同一个套接字上构造一个新的ObjectInputStreamObjectOutputStream而不是在套接字的生命周期中使用相同的套接字,则会发生此问题; 如果你在同一个套接字上使用另一种流; 或者如果您使用对象流来读取或写入不是对象的内容并且您不同步。

如果读取序列化对象的JVM没有对象的正确类/ jar文件,也会发生这种情况。 这通常会导致ClassNotFoundException ,但是如果您有不同的jar / class版本并且版本之间没有更改serialVersionUID ,则会生成StreamCorruptedException 。 (如果存在类名冲突,也可能出现此exception。例如:包含具有相同完整类名的不同类的jar,尽管它们可能也需要相同的serilVersionUID )。

检查客户端是否具有正确版本的jar和类文件。

如果通过添加此方法为类实现自定义反序列化例程,我还有另一种可能性:

 private void readObject( ObjectInputStream objectInputStream ) throws IOException 

然后必须在进一步读取输入流之前调用并调用objectInputStream.defaultReadObject()以正确初始化对象。

我错过了这个,尽管返回的对象没有抛出exception,但是下一次读取的对象流容易引起无效的类型代码exception。

此链接提供有关该过程的更多信息: http : //osdir.com/ml/java.sun.jini/2003-10/msg00204.html 。

如果ObjectInputStream只构造一次,然后只是将它的引用传递给另一个Thread,那么只需将此对象的访问权限包含在synchronized块中,以确保一次只有一个线程可以访问该对象。

无论何时从ObjectInputStream读取,只要在多个线程之间共享,就可以在synchronized块内访问它。


示例代码:(对所有出现的readObject()

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

我也有这个例外。 之所以发生这种情况,是因为我为Server类和Client类使用了两个线程。 我使用一个线程来发送和接收对象。 那没关系。 如果您不熟悉synchronized这是解决问题的简便方法。

java.io.StreamCorruptedException:类型代码无效:00

我最近遇到了这个问题,但没有做OP所做的事情。 快速谷歌搜索,没有发现任何有用的东西,因为我认为我解决了它,我正在用我的解决方案发表评论。

TLDR:没有多个线程同时写入同一输出流(而是轮流)。 当客户端尝试读取数据时会导致问题。 解决方案是锁定写入输出。

我正在做一些非常类似OP的事情,制作一个多人游戏(客户端 – 服务器模型)。 我有一个类似OP的线程正在监听流量。 发生了什么,在我的服务器端是服务器有多个线程同时写入客户端的流(不认为这是可能的,游戏是半转基础)。 正在读取传入流量的客户端线程正在抛出此exception。 为了解决这个问题,我基本上锁定了写入客户端流的部分(在服务器端),因此服务器端的每个线程都必须在写入流之前获取锁。