java.io.StreamCorruptedException: неверный код типа: 00

В общем, я пишу многопользовательскую игру клиент-сервер. У меня есть SeverCommunicationThread, который создает gameThread, если он получает RequestForGame создает gameThread. При отправке исключения 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();
        }
    }
}

Клиентский прокси, который отправляет объекты на сервер, методы запускаются действиями пользователя в графическом интерфейсе

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

}

 user142027327 мая 2012 г., 20:46
addClient (добавляет пользователя в ArrayList типа ClientRepresanative, который содержит сокет, objectouput и входной поток.) он ничего не читает
 Vulcan27 мая 2012 г., 21:48
Хорошо. Кроме того, вы должны очистить ObjectOutputStreams после их создания, чтобы убедиться, что заголовок отправлен. Это может быть причиной того, что вы получаете эту ошибку; заголовок потока еще не прошел. Сбросьте ObjectOutputStream на клиенте и сервере после создания.
 Vulcan27 мая 2012 г., 20:02
Что делает ServerModelManager, когда вы звонитеmodel.addClient(nickname, connectionSocket,outToClient,inFromClient);? В нем может быть код, который портит поток.
 Vulcan27 мая 2012 г., 23:22
Вы не против добавить свой клиентский код туда, где вы пишете объекты?
 user142027327 мая 2012 г., 22:34
Я добавил промывку, ничего не изменилось

Ответы на вопрос(6)

Я недавно столкнулся с этой проблемой, не делая то же самое, что сделал OP. Сделал быстрый поиск в Google и не нашел ничего слишком полезного, и, поскольку я думаю, что решил это, я комментирую свое решение.

TLDR: не допускается, чтобы несколько потоков записывали в один и тот же выходной поток одновременно (вместо этого по очереди). Будет причиной проблем, когда клиентская сторона пытается прочитать данные. Решением является блокировка записи для вывода.

Я делаю что-то очень похожее на OP, создавая многопользовательскую (модель клиент-сервер) игру. У меня есть поток, как OP, который прослушивает трафик. То, что происходило на моей серверной стороне, заключалось в том, что на сервере было несколько потоков, которые одновременно записывали в поток клиента (не думал, что это возможно, игра была полуоборотной). Поток на стороне клиента, который считывал входящий трафик, выдавал это исключение. Чтобы решить эту проблему, я в основном установил блокировку на части, которая записывала в поток клиента (на стороне сервера), чтобы каждый поток на стороне сервера должен был получить блокировку перед записью в поток.

с которой я столкнулся, если вы реализуете специальную процедуру десериализации для класса, добавив этот метод:

private void readObject( ObjectInputStream objectInputStream ) throws IOException

тогда objectInputStream.defaultReadObject () должен быть вызван и вызван перед дальнейшими считываниями входного потока для правильной инициализации объекта.

Я пропустил это, и, несмотря на то, что объект возвращался без исключения, это было следующее чтение потока объекта, которое сбивало с толку недопустимое исключение кода типа.

Эта ссылка предоставляет дополнительную информацию о процессе:http://osdir.com/ml/java.sun.jini/2003-10/msg00204.html.

 19 мар. 2015 г., 00:44
Исправления добавлены.
 17 мар. 2015 г., 22:53
Это не правильное изложение проблемы. Проблема в том, что вы должны позвонитьdefaultReadObject(). После того, как вы сделали это, не важно, чтобы вы прочитали точное количество байтов вашего собственного материала.

если JVM, считывающая сериализованный объект, не имеет правильных файлов класса / jar для объекта. Это обычно приводит кClassNotFoundException, но если у вас разные версии jar / class иserialVersionUID не был изменен между версиями,StreamCorruptedException производится. (Это исключение также возможно при наличии конфликта имен классов. Например: баночка, содержащая другой класс с тем же полным именем класса, хотя им, вероятно, также необходимоserilVersionUID).

Убедитесь, что на стороне клиента установлены правильные версии файлов jar и class.

 06 янв. 2013 г., 09:20
Я сделал этот ответ, поскольку я успешно исправил ошибку в вопросе, установив правильные файлы JAR. Я полагаю, что в моем случае у меня были неправильные версии (и UID версии не был должным образом поддержан), хотя это было некоторое время назад ... Это также возможно при конфликтах имен классов? @ejp Я изменю свой ответ, чтобы указать версии файлов jar - не стесняйтесь, чтобы убрать ваш отрицательный голос, это не мотивирует одного на то, чтобы предоставить другим возможность воспользоваться своим опытом!
 04 янв. 2013 г., 22:49
Нет, это не может. Это условие вызывает ClassNotFoundException.
 13 мар. 2014 г., 04:38
к точке @ drevicko, аналогичноhere.
 07 янв. 2013 г., 01:57
К сожалению, мир не идеален, и не все поддерживаютserialVersionUIDправильно. Там не былоserialVersionUID несоответствие - это не было должным образом поддержано между версиями. Как я уже сказал, в вопросе была указана ошибка, и я решил ее, установив правильную версию. Это НЕ ошибочный диагноз! Это является возможной причиной этой ошибки.

что я использовал два потока для класса сервера и класса клиента. Я использовал один поток для отправки и получения объекта. Тогда это было хорошо. Это простой способ решить проблему, если вы не знакомы сsynchronized.

construct a new ObjectInputStream or ObjectOutputStream over the same socket instead of using the same ones for the life of the socket; use another kind of stream over the same socket as well; or, use the object streams to read or write something that isn't an object and you get out of sync.
 04 янв. 2013 г., 22:48
@ user1420273 Конечно, может, если у вас нет соответствующей синхронизации.
 user142027328 мая 2012 г., 11:37
Сначала я создаю ObjectOutputStream с обеих сторон (Proxy, ServerCommunicationThread). Я создаю его только один раз, а затем просто отправляю ссылку на него другому потоку. Я не использую любой другой вид потока. Единственное, что приходит на ум, - это то, что я пытаюсь прочитать объект из одного и того же ObjectInputStream в 2 потока одновременно. (ServerCommunicationThread, ServerGameThread) Может ли это быть проблемой? (из места исключения я бы так предположил ..)

ObjectInputStream создается только один раз, а затем просто передается ссылка на него другому потоку, а затем просто ограничить доступ этого объекта внутриsynchronized блок, чтобы убедиться, что только один поток может получить доступ к этому объекту одновременно.

Всякий раз, когда вы читаете изObjectInputStream просто получить доступ к нему внутриsynchronized блокировать, если он разделен между несколькими потоками.

Пример кода: (сделайте это для всех случаевreadObject())

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

Ваш ответ на вопрос