错误原因

先直接说错误原因

当使用对象流时,对象头和对象内容一起被写入输出流,而读取时也需要以相同的顺序读取对象头和对象内容

如果读取时的顺序与写入时的顺序不一致,或者在写入或读取对象头和对象内容之间更改了流的状态,则会出现 java.io.StreamCorruptedException: invalid stream header 异常

发生报错的代码

首先可以看一下我的这段代码

客户端使用含有Socket连接的对象输出流向服务器发送了一条Message信息,后续接着发送一个User对象

// 告知服务器进行登录服务Message ask = new Message();ask.setMesType(MessageType.MESSAGE_LOGIN);oos.writeObject(ask);// 发送User信息oos.writeObject(user);

而在服务器,同时有两个地方通过对象输入流从这一个对象输出流读取信息

1号读取Message对象

2号读取User对象

/**1号对象输入流*/ObjectInputStream ois = new ObjectInputStream(socket.getInputStream());// 读取功能请求Message ask = (Message) ois.readObject();function = ask.getMesType();System.out.println(function);
/**2号对象输入流*/// 获取客户端数据,使用对象输入流获取User对象 ObjectInputStream ois = new ObjectInputStream(socket.getInputStream()); User user = (User) ois.readObject();

此时当服务器代码运行到2号对象输入流是,出现了java.io.StreamCorruptedException: invalid stream header: 7372001的错误信息

经过查找资料,发现原因

在这个例子中,客户端使用同一个对象输出流依次发送了 MessageUser 对象,但服务器端使用了两个不同的对象输入流同时读取这个输出流,这导致两个输入流读取的顺序可能不同,从而导致异常

简单说就是

对象输出流序列化数据时,会把数据的数据格式(可以理解为数据存在的形式、在代码中的位置等等)写在流的对象头中,以供于输入流按照格式进行读取

通俗点说

一个工人在做事之前,需要先拿到经理人给的表格,这张表格上写了他要干什么,先做什么后做什么

而当1号对象输入流读取了Message对象后,Message对象就被消耗掉了,2号对象输入流读取时,会直接从User对象这里读起

但是2号对象拿到的这张表格和1号对象拿到的是一样的,上面写了Message在最前面,然后是User,可是2号读取时发现Message不见了,于是报错了

如何修改

为了避免这种异常,最好保证一个输出流对应一个输入流

在类的最前面定义广域的输入流

ObjectInputStream ois; // 对象输入流,用于读取客户端发送消息

随后在读取时都使用这一个输入流去读取输出流

ois = new ObjectInputStream(socket.getInputStream());// 读取功能请求Message ask = (Message) ois.readObject();function = ask.getMesType();System.out.println(function);
// 获取输出流,用于返回登录信息ObjectOutputStream oos = new ObjectOutputStream(socket.getOutputStream());