проблема при отправке сериализуемых объектов с помощью ObjectInputStream - PullRequest
3 голосов
/ 21 июня 2010

фрагмент кода сервера:

 public void run() {
        try {
          // Create data input and output streams
          ObjectInputStream inputFromClient = new ObjectInputStream(
            socket.getInputStream());
          ObjectOutputStream outputToClient = new ObjectOutputStream(
            socket.getOutputStream());

          while (true) {

         cop = inputFromClient.readObject();

         String[][] m1=new String[][] {{"1", "1","1"}};
         Object xx=new getSerialModel(m1);
         outputToClient.reset();
         outputToClient.writeObject(xx);

         outputToClient.flush();


          }
        }

фрагмент от Клиента:

//////////////
    /// sockt jop
    try {
    // Create a socket to connect to the server
   socket = new Socket("127.0.0."+Math.round(50+Math.random()*50), 8000);

    // Create an output stream to send data to the server
   toServer = new ObjectOutputStream(socket.getOutputStream());
   toServer.flush();

  }
  catch (IOException ex) {
    msgArea.append('\n' + ex.toString() + '\n');
  }
///////////////////
//***
///////////////////
buttonSave.addActionListener(new ActionListener()

{ public void actionPerformed(ActionEvent ev)

{

System.out.println("Saving data is not implemented yet.");
        String[][] m1={{"0","0","0"}};
        for ( int i = 0 ; i < tableModel.getRowCount() ; i++ ){
            { for ( int j = 0 ; j < tableModel.getColumnCount() ; j++ )
                    m1[i][j]=(String)tableModel.getValueAt(i, j) ;
            }
        }

        getSerialModel obt =new getSerialModel(m1);

        try{
            toServer.reset();
        toServer.writeObject(obt);
       toServer.flush();


        }
        catch (Exception ex) {
     msgArea.append("cant reach the server its may be off" + '\n');
   }

}

});
// button send msg
    buttonsendtest.addActionListener(new ActionListener()

{ public void actionPerformed(ActionEvent ev)

{
        try{


       fromServer = new ObjectInputStream(socket.getInputStream());

       Object mdata = fromServer.readObject();
       tableModel.setDataVector((((getSerialModel)mdata).getmodel()), columnNames);
       table.updateUI();

        }
        catch (Exception ex) {
            System.out.print(ex.getStackTrace());
     msgArea.append("cant reach the server its may be off "+ ex.toString() + '\n');
   }

}
});

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

java.io.StreamCorruptedException: invalid stream header: 00007571

как я могу это исправить?

Ответы [ 4 ]

7 голосов
/ 21 июня 2010

Если вы создаете несколько экземпляров ObjectInputStream последовательно для одного и того же потока ввода сокетов, это кажется плохой идеей. Если сервер записывает несколько объектов в один и тот же поток вывода, существует информация, связанная с сериализацией, которая отправляется только один раз для каждого уникального объекта, и только первый экземпляр ObjectInputStream на клиенте сможет надежно прочитать это. Использование только одного экземпляра ObjectInputStream для каждого входного потока сокета и одного экземпляра ObjectOutputStream для каждого выходного потока сокета, вероятно, является наиболее безопасной реализацией.

Кроме того, если вы записываете несколько объектов в один и тот же ObjectOutputStream экземпляр на стороне сервера (т. Е. Несколько вызовов writeObject ()), это может привести к проблемам заголовка потока из-за потенциально многократные ссылки на одни и те же объекты (обычно вложенные ссылки), когда они читаются входным потоком клиента

Эта проблема возникает, когда выходной поток объекта оборачивает выходной поток сокета, поскольку во время обычной сериализации вторая и последующие ссылки на объект не описывают объект, а скорее используют только ссылку. ObjectInputStream клиента не восстанавливает объекты должным образом по какой-то причине из-за разницы в информации заголовка, которую он ожидает (он не сохраняет ее от предыдущих вызовов readObject ()); похоже, это происходит только с потоками сокетов, а не с файловым вводом-выводом и т. д. Эта проблема возникает не при вызове first readObject (), а во втором и последующих.

Если вы хотите продолжать использовать один и тот же поток сокетов для записи нескольких объектов, вам потребуется что-то вроде следующего в коде сервера:

objectOut.reset()
objectOut.writeObject(foo);

Вызов reset () повторно инициализирует поток, игнорируя состояние любых объектов, ранее отправленных по потоку. Это гарантирует, что каждый объект отправляется полностью без ссылок типа дескриптора, которые обычно используются для сжатия данных ObjectOutputStream и предотвращения дублирования. Это менее эффективно, но не должно быть никакого повреждения данных при чтении клиентом.

0 голосов
/ 21 июня 2010

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

Или вы пытаетесь использовать ObjectInputStream до создания соответствующего ObjectOutputStream, и это делает недействительной связь между ними. ObjectOutputStream записывает заголовок потока сериализации при его создании, и если он не был создан до соответствующего ObjectOutputStream, этот заголовок теряется.

0 голосов
/ 21 июня 2010

Вы пытаетесь прочитать объект типа «Объект». Так ли это было сериализовано? Вам нужно убедиться, что вы читаете объект в том же классе, из которого он был написан, помните те досадные предупреждения serialVersionUID, которые появляются? Это является ключом к сериализации и реконструкции объектов, следовательно, необходимо сопоставлять классы. Также причина, по которой вам нужно обновить свой UID при изменении структуры вашего класса.

0 голосов
/ 21 июня 2010

Из документации для ObjectInputStream.readObject () я цитирую:

Чтение объекта из ObjectInputStream.Класс объекта, сигнатура класса и значения нетранзитивных и нестатических полей класса и всех его супертипов считываются.Десериализацию по умолчанию для класса можно переопределить с помощью методов writeObject и readObject.Объекты, на которые ссылается этот объект, считываются транзитивно, поэтому readObject восстанавливает полный эквивалентный граф объектов.

Корневой объект полностью восстанавливается, когда полностью восстанавливаются все его поля и объекты, на которые он ссылается.На этом этапе обратные вызовы проверки объекта выполняются в порядке, основанном на их зарегистрированных приоритетах.Обратные вызовы регистрируются объектами (в специальных методах readObject) по мере их индивидуального восстановления.

Исключения создаются для проблем с InputStream и для классов, которые не должны быть десериализованы.Все исключения являются фатальными для InputStream и оставляют его в неопределенном состоянии;вызывающий может игнорировать или восстанавливать состояние потока.

Specified by:
    readObject in interface ObjectInput

Returns:
    the object read from the stream 
Throws:
    ClassNotFoundException - Class of a serialized object cannot be found. 
    InvalidClassException - Something is wrong with a class used by serialization. 
    StreamCorruptedException - Control information in the stream is inconsistent. 
    OptionalDataException - Primitive data was found in the stream instead of objects. 
    IOException - Any of the usual Input/Output related exceptions.

Я предполагаю, что вы пытаетесь прочитать объект до того, как он был записан в поток объекта, илитот, где выходной поток не был очищен.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...