3

服务器代码片段:

 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

4 回答 4

7

如果您为同一个套接字输入流串联创建多个 ObjectInputStream 实例,这似乎是个坏主意。如果服务器将多个对象写入同一个输出流,那么每个唯一对象只会发送一次与序列化相关的信息,并且只有客户端上的第一个 ObjectInputStream 实例才能可靠地读取它。每个套接字输入流只使用一个 ObjectInputStream 实例,每个套接字输出流只使用一个 ObjectOutputStream 实例可能是最安全的实现。

此外,如果您将多个对象写入服务器端的同一个ObjectOutputStream 实例(即多个 writeObject() 调用),这可能会导致流标头问题,因为当它们可能对同一对象(通常是嵌套引用)进行多次引用时由客户端的输入流读取

当对象输出流包装套接字输出流时会出现此问题,因为在正常序列化期间,对对象的第二次和以后的引用不描述对象,而仅使用引用。由于某些原因,客户端的 ObjectInputStream 无法正确重建对象,因为它所期望的标头信息存在差异(它不会从先前的 readObject() 调用中保留它);这似乎只发生在套接字流上,而不是文件 I/O 等。这个问题不会在第一次readObject() 调用中发生,而是在第二次和后续调用中发生。

如果您想继续使用相同的套接字流来写入多个对象,您将需要在服务器代码中类似以下内容:

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

reset() 调用重新初始化流,忽略之前沿流发送的任何对象的状态。这确保了每个对象都被完整地发送,而没有通常用于压缩 ObjectOutputStream 数据并避免重复的句柄类型引用。它的效率较低,但客户端读取时应该没有数据损坏。

于 2010-06-21T17:40:04.677 回答
0

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.

我猜你是在一个对象被写入对象流之前尝试读取一个对象,或者一个输出流没有被刷新的对象。

于 2010-06-21T16:48:01.167 回答
0

您正在尝试读取“对象”类型的对象。是这样连载的吗?您需要确保将对象读入与写入对象相同的类中,还记得出现的那些讨厌的 serialVersionUID 警告吗?这是对象序列化和重构的关键,因此需要匹配类。这也是您在类结构更改时需要更新 UID 的原因。

于 2010-06-21T17:11:23.123 回答
-1

也许您正试图从流中多次读取同一个对象,而服务器只写入一次该对象。

或者您尝试在创建相应的 ObjectOutputStream 之前使用 ObjectInputStream,这会使两者之间的通信无效。ObjectOutputStream 在创建时会写入序列化流标头,如果它不是在相应的 ObjectOutputStream 之前创建的,则该标头会丢失。

于 2010-06-21T16:54:07.470 回答