java.io.StreamCorruptedException

cathydou 2009-04-26 09:51:57
做的是和QQ的远程协助差不多的系统,在图像接收和显示时出现了streamcorruptedexception,而且是不定时出现,异常已经调了很长一段时间仍然没有头绪,现将部分代码贴出,希望帮忙解决。
java.io.StreamCorruptedException: invalid type code: AC
at java.io.ObjectInputStream.readObject0(Unknown Source)
at java.io.ObjectInputStream.readObject(Unknown Source)
at remote_control.Communication.TCP.CommunicationTCPServer.Receive(CommunicationTCPServer.java:75)
at remote_control.Thread.ReceiveMessage.ReceiveMessageThreadTCP.run(ReceiveMessageThreadTCP.java:34)
类CommunicationTCPServer和CommunicationTCPClient用于建立服务器和客户机连接,并且负责发送和接收图像和信息,Protocol是将图像和鼠标键盘信息进行序列化的类
CommunicationTCPClient

public CommunicationTCPClient(String IP) {
try {
this.connection = new Socket(IP, CommunicationConst.port);
// 建立socket连接
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}

/**
* @描述 发送信息函数
* @param protocol
* 要发送的信息
*/
public void Send(Protocol protocol) {
try {
this.out = this.connection.getOutputStream();
// 将输出流与socket输出流关联
this.output = new ObjectOutputStream(this.out);
// 用关联过的输出流实例对象输出流
if (output != null) {
this.output.writeObject(protocol);
// 将信息写如输出流
this.output.flush();
// 推出
}
} catch (IOException e) {
// TODO Auto-generated catch block
Dispose();
e.printStackTrace();
}
}

/**
* @描述 信息接收函数
* @return 返回读取到的信息
*/
public Protocol Receive() {
try {
this.in = this.connection.getInputStream();
// 关联输入流与socket输入流
this.input = new ObjectInputStream(this.in);
// 用输入流实例对象输入流
if (input != null) {
this.procotol = (Protocol) this.input.readObject();
// 将读入信息存到procotol
}
} catch (IOException e) {
Dispose();
e.printStackTrace();
// 如发生异常则关闭连接
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
return this.procotol;
// 返回所读取的信息
}


CommunicationTCPServer

/**
* @描述 构造函数 用于监听连接
*/
public CommunicationTCPServer() {
try {
if (CommunicationTCPServer.server == null) {
CommunicationTCPServer.server = new ServerSocket(
CommunicationConst.port);
// 新建一个欢迎套接字,并且保证只有一个欢迎套接字
}
this.connection = CommunicationTCPServer.server.accept();
// 服务器端的套接字与客户机端连接
} catch (IOException e) {
e.printStackTrace();
}
}

/**
* @描述 发送报文
* @param protocol
* 要发送的信息
*/
public void Send(Protocol protocol) {
try {
out = connection.getOutputStream();
// 获得输出流
this.output = new ObjectOutputStream(this.out);
// 获得对象输出流
if (output != null) {
this.output.writeObject(protocol);
// 将报文写入到对象输出流
this.output.flush();
// 刷新输出流,将流中数据推出
}

} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
Dispose();
// 如发生socket相关异常关闭socket
}
}

/**
* @描述 接收报文
* @return Protocol 返回读取的信息
*
*/
public Protocol Receive() {
try {
this.in = this.connection.getInputStream();
// 获得输入流
this.input = new ObjectInputStream(in);
// 获得对象输入流
if (input != null) {
this.procotol = (Protocol) input.readObject();
// 从输入流中读取报文
}
} catch (IOException e) {
e.printStackTrace();
Dispose();
// 如发生socket相关异常,尝试关闭socket
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
return this.procotol;
// 将报文返回
}


Protocol

/**
* @描述 此函数为鼠标事件的构造函数
*/
public Protocol(MouseEvent e1, int eventflag, int m) {

x = e1.getX();
// 提取鼠标事件的X坐标
y = e1.getY();
// 提取鼠标事件的Y坐标
if (e1.getButton() == 1)
button = InputEvent.BUTTON1_MASK;
// 如果是左键赋予相应的键值
else if (e1.getButton() == 2)
button = InputEvent.BUTTON2_MASK;
// 如果是中键赋予相应的键值
else
button = InputEvent.BUTTON3_MASK;
// 如果是中间赋予相应的键值
flag = m;
// 控制信息赋值
eventFlag = eventflag;
// 标识为何种触发事件,如按键盘,右击鼠标等
}
/**
* @描述 此函数为键盘事件构造函数
* @param e2
* 键盘事件
* @param eventflag
* 标识为何种触发事件
* @param flag1
* 控制标识
*/
public Protocol(KeyEvent e2, int eventflag, int m) {
keyCode = e2.keyCode;
// 提取键盘按键键值
flag = m;
// 给控制事件赋值
eventFlag = eventflag;
// 给事件标识赋值
}
/**
* @param image为要传输的图像,i为连接控制信息
* @描述 构造函数讲传递过来的图片写入一个字节数组中保存,以便完成 序列化的传输。以及将flag信息读入。
*/
public Protocol(BufferedImage image, int i) {
flag = i;
// 读入控制信息
ByteArrayOutputStream out = new ByteArrayOutputStream();
// 实例化一个字节流用以将图片转换成字节数组
try {
if (image != null && out != null)
ImageIO.write(image, "jpg", out);
// 将图片写入字节流中
if (out != null)
a = out.toByteArray();
// 将字节流转换成字节数组,因为字节流也不能序列化传输
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}

}
...全文
1897 9 打赏 收藏 转发到动态 举报
写回复
用AI写文章
9 条回复
切换为时间正序
请发表友善的回复…
发表回复
humanity 2011-06-24
  • 打赏
  • 举报
回复
在工作时把每个片段的长度设计得小一点,让它几乎每次都能把一个片段发送成功。
humanity 2011-06-24
  • 打赏
  • 举报
回复
我猜想其中一个可能:

每次 Receive 不一定能拿到所有的字节,比如网络很慢的时候,可能先拿了前面 60% 的数据,这时组装成 Object 时会出错,下次再 Receive 拿到后面 40% 再组装依然出错,但如果上次 60% 组装出错时把数据缓存起来,等到后面 40% 到了的时候再试一次或许就成功了,因为每次都不能估计准确数据是否完整,所以不合适每次都拼装试验;一个可性的办法是设计时就先假定每个消息可以划分成多个片段 fragment 发送出去,每个片段是有最大长度的,有个消息头会说明它的长度和它的次序号以及表明这个片段是否是最后一个片段的标记位,接收方收到消息后根据是否是最后一条消息片段的标记位来决定是否要将之前收到的几个片段接装成一个 ByteArrayInputStream 来尝试组装成 Object,当标记位不是最后一个片段时就将数据缓存起来;

这种做法适合数据比较长或网络状态不是很好的通信过程,也是一个比较可靠的方法,我们不能假设总是可以像在本地局域网那样快速的处理消息,要想到互联网那很烂的网络环境下让它也能工作。




gezhonglei2007 2011-06-24
  • 打赏
  • 举报
回复
我也是遇到这样的问题!好些人也遇到同样的问题,有的解答是说,可能是在同一个线程里面多次用了用了new objectOutputStream(socket.getOutputStream())。
可以尝试把objectOutputStream保存在一个公有变量或静态变量中使用objectOutputStream的都用这个公用管道输出!
无情剑帅 2010-01-19
  • 打赏
  • 举报
回复
说说解决办法吧!
yangning_mail 2009-05-31
  • 打赏
  • 举报
回复
多线程共用一个连接,我也遇到过类似问题。
studying_ 2009-05-03
  • 打赏
  • 举报
回复
streamcorruptedexception 流中断异常,估计是多线程,共用一个,引起了冲突
老紫竹 2009-04-28
  • 打赏
  • 举报
回复
this.out = this.connection.getOutputStream();


我怀疑你是不是几个线程共用了一个connection, 造成并发冲突
yangzhiwei3340 2009-04-27
  • 打赏
  • 举报
回复
还是要仔细检查吧 呵呵
xuezhanliang6886 2009-04-27
  • 打赏
  • 举报
回复
顶!学习!

58,454

社区成员

发帖
与我相关
我的任务
社区描述
Java Eclipse
社区管理员
  • Eclipse
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧