2012-01-09 27 views
1

我遇到了一個不尋常的問題,導致我將頭髮撕掉。我有Netty客戶端/服務器設置。服務器向客戶端發送一個命令對象。然後,客戶端將在命令對象中找到的每個二進制命令發送到連接到其本地串行端口的設備。每個命令(二進制字符串)的答案都存儲在命令對象中,並且所有命令都執行完畢後,命令對象返回給服務器。所以我在客戶端和服務器管道中都使用了ObjectEncoder和ObjectDecoder。Netty ObjectDecoder拋出java.io.StreamCorruptedException:塊數據意外結束

我有一個特定的,可重複的情況下,當一個特定的命令對象返回到服務器時,服務器拋出「java.io.StreamCorruptedException:塊數據的意外結束」(下面的堆棧跟蹤)。我在服務器和客戶端都使用Netty 3.2.7-Final,我在客戶端和服務器上都使用Oracle Java 1.7.0_02。

真正在做什麼的是,如果我在Windows 7本地運行客戶端&服務器,則作業運行正常。如果我在Debian Linux系統上遠程運行服務器,那麼特定作業將正常運行。但是,當我在Linux CentOS 6系統上運行服務器時,除時間外,作業失敗。 (客戶端必須在Windows環境下運行)

任何有關如何進一步調試的建議都非常受歡迎。我已經看過擴展ObjectEncoder,所以我可以將序列化的對象轉儲到磁盤上以查看線路上正在放置什麼,但我無法弄清楚如何獲取由編碼方法返回的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) 

回答

1

由於同時解碼出現該問題,

可以HEX-轉儲接收到的信道緩衝器的解碼前的日誌,並稍後進行分析。你必須有你自己的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(); 
} 
+0

謝謝,我會試試看。在將編碼對象放到電線上之前,是否有一種方便的方式對編碼對象做同樣的事情,以便我可以檢查發送的內容是什麼? – user497087 2012-01-09 18:30:19

+0

在調用super.decode()之前不應該存在轉儲嗎? – user497087 2012-01-09 18:32:31

+0

超級類只是一個幀解碼器,所以實際的對象解碼發生在readObject不是嗎?,你可以爲ObjectEncoder做類似的事情我認爲。 – 2012-01-09 18:52:44