Centos Netty ObjectDecoder抛出java.io.StreamCorruptedException:块数据意外结束

Centos Netty ObjectDecoder抛出java.io.StreamCorruptedException:块数据意外结束,centos,netty,centos6,Centos,Netty,Centos6,我有一个不寻常的问题,导致我把头发扯下来。我有一个Netty客户端/服务器设置。服务器向客户端发送一个命令对象。然后,客户机将在command对象中找到的每个二进制命令发送到连接到其本地串行端口的设备。每个命令的答案(二进制字符串)存储在command对象中,当所有命令都已执行时,command对象将返回到服务器。因此,我在客户机和服务器管道中使用ObjectEncoder和ObjectDecoder 我有一个特定的、可重复的例子,当一个特定的命令对象返回到服务器时,服务器抛出“java.io.

我有一个不寻常的问题,导致我把头发扯下来。我有一个Netty客户端/服务器设置。服务器向客户端发送一个命令对象。然后,客户机将在command对象中找到的每个二进制命令发送到连接到其本地串行端口的设备。每个命令的答案(二进制字符串)存储在command对象中,当所有命令都已执行时,command对象将返回到服务器。因此,我在客户机和服务器管道中使用ObjectEncoder和ObjectDecoder

我有一个特定的、可重复的例子,当一个特定的命令对象返回到服务器时,服务器抛出“java.io.StreamCorruptedException:unexpected end of block data”(下面的堆栈跟踪)。我在服务器和客户端上都使用Netty 3.2.7-Final,在客户端和服务器上都使用Oracle Java 1.7.002

真正让我头疼的是,如果我在Windows7下本地运行客户机和服务器,那么作业就会正常运行。如果我在Debian Linux系统上远程运行服务器,那么特定作业将正确运行。但是,当我在Linux CentOS 6系统上运行服务器时,每次作业都会失败,只有一个例外。(客户端必须在Windows环境中运行)

任何关于如何进一步调试的建议都是非常受欢迎的。我已经研究了扩展ObjectEncoder,这样我可以将序列化对象转储到磁盘,以查看正在连接的内容,但我无法确定如何获取encode方法返回的ChannelBuffer的内容

java.io.StreamCorruptedException: unexpected end of block data
    at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1369)
    at java.io.ObjectInputStream.defaultReadFields(ObjectInputStream.java:1964)
    at java.io.ObjectInputStream.defaultReadObject(ObjectInputStream.java:498)
    at java.lang.Throwable.readObject(Throwable.java:913)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:601)
    at java.io.ObjectStreamClass.invokeReadObject(ObjectStreamClass.java:991)
    at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:1866)
    at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1771)
    at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1347)
    at java.io.ObjectInputStream.defaultReadFields(ObjectInputStream.java:1964)
    at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:1888)
    at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1771)
    at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1347)
    at java.io.ObjectInputStream.readObject(ObjectInputStream.java:369)
    at java.util.ArrayList.readObject(ArrayList.java:733)
    at sun.reflect.GeneratedMethodAccessor70.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:601)
    at java.io.ObjectStreamClass.invokeReadObject(ObjectStreamClass.java:991)
    at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:1866)
    at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1771)
    at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1347)
    at java.io.ObjectInputStream.defaultReadFields(ObjectInputStream.java:1964)
    at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:1888)
    at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1771)
    at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1347)
    at java.io.ObjectInputStream.readObject(ObjectInputStream.java:369)
    at org.jboss.netty.handler.codec.serialization.ObjectDecoder.decode(ObjectDecoder.java:129)
    at org.jboss.netty.handler.codec.frame.FrameDecoder.callDecode(FrameDecoder.java:282)
    at org.jboss.netty.handler.codec.frame.FrameDecoder.messageReceived(FrameDecoder.java:214)
    at org.jboss.netty.channel.Channels.fireMessageReceived(Channels.java:274)
    at org.jboss.netty.channel.Channels.fireMessageReceived(Channels.java:261)
    at org.jboss.netty.channel.socket.nio.NioWorker.read(NioWorker.java:351)
    at org.jboss.netty.channel.socket.nio.NioWorker.processSelectedKeys(NioWorker.java:282)
    at org.jboss.netty.channel.socket.nio.NioWorker.run(NioWorker.java:202)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1110)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:603)
    at java.lang.Thread.run(Thread.java:722)

由于问题发生在解码时

您可以在解码之前将接收到的通道缓冲区十六进制转储到日志中,然后对其进行分析。您必须有自己版本的ObjectDecoder,如

    @Override
protected Object decode(
        ChannelHandlerContext ctx, Channel channel, ChannelBuffer buffer) throws Exception {

    ChannelBuffer frame = (ChannelBuffer) super.decode(ctx, channel, buffer);
    if (frame == null) {
        return null;
    }


    logger.debug("Hex dump of object frame [" + ChannelBuffers.hexDump(frame) + "]");

    return new CompactObjectInputStream(
            new ChannelBufferInputStream(frame), classResolver).readObject();
}

由于问题发生在解码时

您可以在解码之前将接收到的通道缓冲区十六进制转储到日志中,然后对其进行分析。您必须有自己版本的ObjectDecoder,如

    @Override
protected Object decode(
        ChannelHandlerContext ctx, Channel channel, ChannelBuffer buffer) throws Exception {

    ChannelBuffer frame = (ChannelBuffer) super.decode(ctx, channel, buffer);
    if (frame == null) {
        return null;
    }


    logger.debug("Hex dump of object frame [" + ChannelBuffers.hexDump(frame) + "]");

    return new CompactObjectInputStream(
            new ChannelBufferInputStream(frame), classResolver).readObject();
}

谢谢,我试试看。有没有一种方便的方法可以在编码对象被连接之前对其执行相同的操作,这样我就可以检查发送的是接收的是什么?super类只是一个帧解码器,所以实际的对象解码发生在readObject,不是吗?我想你可以对ObjectEncoder执行类似的操作。谢谢,我会尝试一下。有没有一种方便的方法可以在编码对象上线之前对其执行相同的操作,这样我就可以检查发送的是接收的是什么?超类只是一个帧解码器,所以实际的对象解码发生在readObject,不是吗?我想,你可以对ObjectEncoder执行类似的操作。