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

2019-05-16 14:02发布

所以基本上我写的客户端 - 服务器的多人游戏。 我有,如果他收到一个RequestForGame创建gameThread创建一个gameThread一个SeverCommunicationThread。 当我发送RequestForGame抛出异常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();
    }
}

}

Answer 1:

如果你这个问题可能发生

  • 构造一个新ObjectInputStreamObjectOutputStream而不是使用套接字的生命一样的人在同一个插座;
  • 用另一种流在同一插座的为好; 要么,
  • 使用对象流读或写的东西是不是一个对象,你会得到不同步。


Answer 2:

如果JVM读取序列化对象没有该对象的正确的类/ jar文件也会发生这种情况。 这通常会导致一个ClassNotFoundException ,但如果你有不同的JAR /类版本和serialVersionUID没有更改版本之间,一个StreamCorruptedException产生。 (此异常也可能是可能的,如果有一个类名冲突如:含有相同完整的类名称不同的类,但他们可能也需要同样的罐子serilVersionUID )。

检查客户端拥有罐子和类文件的正确版本。



Answer 3:

还有,我加入这个方法横跨在那里,如果你实现了一类自定义序列化程序跑了另一种可能性:

private void readObject( ObjectInputStream objectInputStream ) throws IOException

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

我错过了这一点,尽管被抛出没有例外返回对象这是容易混淆提出的无效类型代码异常物体流的下一个读。

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



Answer 4:

如果ObjectInputStream构造只有一次,然后刚刚通过它给其他线程的引用,然后简单地附上这里面对象的访问synchronized块,以确保只有一个线程可以同时访问该对象。

每当你从阅读ObjectInputStream只是访问它的内部synchronized块如果多个线程之间共享。


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

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


Answer 5:

我也有这种例外。 它的发生是因为我用了两个线程服务器类和客户端类。 我使用一个线程对象发送和接收的事情。 然后,它是确定的。 这是,如果你不熟悉来解决这个问题简单的方式synchronized



Answer 6:

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

我最近就遇到了这个问题,而不是做什么OP做虽然。 做了一个快速谷歌搜索,并没有发现任何东西,太乐于助人,因为我想我解决了这个问题,我做我的解决方案的注释。

TLDR:不要有多个线程写在同一时间(而不是轮流)相同的输出流。 会造成当客户端尝试读取数据的问题。 解决方法是把一个锁在写入输出。

我做的非常相似,OP的东西,使多人(客户端 - 服务器模型)的游戏。 我有一个像OP被监听业务的线程。 发生了什么事,在我的服务器端是服务器上存在的同时写入到客户端的流多线程(不认为这是可能的,比赛是半转动座)。 客户端线程正在读的传入流量被扔这个异常。 为了解决这个问题我基本上把锁上写给客户端的数据流(在服务器端),所以在服务器端每个线程必须写入流之前获得锁的一部分。



文章来源: java.io.StreamCorruptedException: invalid type code: 00