由于对象流解析的数据与流的头部信息不匹配导致异常 java.io.StreamCorruptedException: invalid stream header
今天在做韩顺平老师的多人在线通讯系统,在服务器读取客户端发送的Message对象和User对象时,出现了 java.io.StreamCorruptedException: invalid stream header这个报错,找了很久的原因,下面总结一下希望也能帮助到和我有一样问题的人,同时也是自己做一下笔记
错误原因
先直接说错误原因
当使用对象流时,对象头和对象内容一起被写入输出流,而读取时也需要以相同的顺序读取对象头和对象内容
如果读取时的顺序与写入时的顺序不一致,或者在写入或读取对象头和对象内容之间更改了流的状态,则会出现 java.io.StreamCorruptedException: invalid stream header 异常
发生报错的代码
首先可以看一下我的这段代码
客户端使用含有Socket连接的对象输出流向服务器发送了一条Message信息,后续接着发送一个User对象
▼java复制代码// 告知服务器进行登录服务 Message ask = new Message(); ask.setMesType(MessageType.MESSAGE_LOGIN); oos.writeObject(ask); // 发送User信息 oos.writeObject(user);
而在服务器,同时有两个地方通过对象输入流从这一个对象输出流读取信息
1号读取Message对象
2号读取User对象
▼java复制代码/** 1号对象输入流 */ ObjectInputStream ois = new ObjectInputStream(socket.getInputStream()); // 读取功能请求 Message ask = (Message) ois.readObject(); function = ask.getMesType(); System.out.println(function);
▼java复制代码/** 2号对象输入流 */ // 获取客户端数据,使用对象输入流获取User对象 ObjectInputStream ois = new ObjectInputStream(socket.getInputStream()); User user = (User) ois.readObject();
此时当服务器代码运行到2号对象输入流是,出现了java.io.StreamCorruptedException: invalid stream header: 7372001的错误信息
经过查找资料,发现原因
在这个例子中,客户端使用同一个对象输出流依次发送了 Message 和 User 对象,但服务器端使用了两个不同的对象输入流同时读取这个输出流,这导致两个输入流读取的顺序可能不同,从而导致异常
简单说就是
对象输出流序列化数据时,会把数据的数据格式(可以理解为数据存在的形式、在代码中的位置等等)写在流的对象头中,以供于输入流按照格式进行读取
通俗点说
一个工人在做事之前,需要先拿到经理人给的表格,这张表格上写了他要干什么,先做什么后做什么
而当1号对象输入流读取了Message对象后,Message对象就被消耗掉了,2号对象输入流读取时,会直接从User对象这里读起
但是2号对象拿到的这张表格和1号对象拿到的是一样的,上面写了Message在最前面,然后是User,可是2号读取时发现Message不见了,于是报错了
如何修改
为了避免这种异常,最好保证一个输出流对应一个输入流
在类的最前面定义广域的输入流
▼java复制代码ObjectInputStream ois; // 对象输入流,用于读取客户端发送消息
随后在读取时都使用这一个输入流去读取输出流
▼java复制代码ois = new ObjectInputStream(socket.getInputStream()); // 读取功能请求 Message ask = (Message) ois.readObject(); function = ask.getMesType(); System.out.println(function);
▼java复制代码// 获取输出流,用于返回登录信息 ObjectOutputStream oos = new ObjectOutputStream(socket.getOutputStream());
