2013-05-31 21 views
1

我正在用項目中的Netty4替換Netty3。我使用Google協議緩衝區作爲數據傳輸。當關閉在Netty3中正常工作的通道時,我收到了一個異常。[Netty 4 CR2]通過使用用戶定義的編碼器和解碼器關閉通道時出現異常

吼叫是異常的詳細信息:

io.netty.handler.codec.DecoderException: java.lang.IndexOutOfBoundsException: readerIndex(0) + length(4) exceeds writerIndex(0): PooledUnsafeDirectByteBuf(ridx: 0, widx: 0, cap: 4096) 
    at io.netty.handler.codec.ByteToMessageDecoder.channelInactive(ByteToMessageDecoder.java:95) 
    at io.netty.channel.DefaultChannelHandlerContext.invokeChannelInactive(DefaultChannelHandlerContext.java:801) 
    at io.netty.channel.DefaultChannelHandlerContext.fireChannelInactive(DefaultChannelHandlerContext.java:787) 
    at io.netty.channel.DefaultChannelPipeline.fireChannelInactive(DefaultChannelPipeline.java:808) 
    at io.netty.channel.AbstractChannel$AbstractUnsafe$9.run(AbstractChannel.java:725) 
    at io.netty.util.concurrent.SingleThreadEventExecutor.runAllTasks(SingleThreadEventExecutor.java:364) 
    at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:326) 
    at io.netty.util.concurrent.SingleThreadEventExecutor$2.run(SingleThreadEventExecutor.java:114) 
    at java.lang.Thread.run(Unknown Source) 
Caused by: java.lang.IndexOutOfBoundsException: readerIndex(0) + length(4) exceeds writerIndex(0): PooledUnsafeDirectByteBuf(ridx: 0, widx: 0, cap: 4096) 
    at io.netty.buffer.AbstractByteBuf.checkReadableBytes(AbstractByteBuf.java:1120) 
    at io.netty.buffer.AbstractByteBuf.readInt(AbstractByteBuf.java:627) 
    at com.fhq.mathematica.netty.MMADecoder.decode(MMADecoder.java:17) 
    at io.netty.handler.codec.ByteToMessageDecoder.decodeLast(ByteToMessageDecoder.java:168) 
    at io.netty.handler.codec.ByteToMessageDecoder.channelInactive(ByteToMessageDecoder.java:91) 

這裏的編碼器:(消息是在頂層協議緩衝器的接口。)

public class MessageEncoder extends MessageToByteEncoder<Message>{ 
    @Override 
    protected void encode(ChannelHandlerContext ctx, Message msg, ByteBuf out) 
      throws Exception { 
     byte[] data = msg.toByteArray(); 
     out.writeInt(data.length); 
     out.writeBytes(data); 
    } 
} 

這裏的解碼器:

public class MMADecoder extends ByteToMessageDecoder{ 
    @Override 
    protected void decode(ChannelHandlerContext ctx, ByteBuf in, 
      MessageBuf<Object> out) throws Exception { 
     in.markReaderIndex(); 
     int dataLength = in.readInt(); 
     if (in.readableBytes() < dataLength) { 
      in.resetReaderIndex(); 
      return; 
     } 
     byte[] decoded = new byte[dataLength]; 
     in.readBytes(decoded); 
     out.add(MathematicaTask.parseFrom(decoded)); 
    } 
} 

當我只是轉移MathematicaTask對象,它工作正常(客戶端和服務器解析消息都正確LY)。但是當我關閉頻道時,解碼器中會出現異常。

int dataLength = in.readInt(); 

任何人都可以找出問題嗎? Mush讚賞!

順便說一句:我試過ObjectEncoder和ObjectDecoder,然後一切都很好。所以在我的解碼器/編碼器中一定有一些問題。

回答

0

您需要檢查在調用ByteBuf.readInt()之前是否有足夠的字節要讀取。

因此,像這樣:

public class MMADecoder extends ByteToMessageDecoder{ 
    @Override 
    protected void decode(ChannelHandlerContext ctx, ByteBuf in, 
      MessageBuf<Object> out) throws Exception { 
     if (in.readableBytes < 4) { 
      return; 
     } 
     in.markReaderIndex(); 
     int dataLength = in.readInt(); 
     if (in.readableBytes() < dataLength) { 
      in.resetReaderIndex(); 
      return; 
     } 
     byte[] decoded = new byte[dataLength]; 
     in.readBytes(decoded); 
     out.add(MathematicaTask.parseFrom(decoded)); 
    } 
} 
+0

謝謝!有用!但爲什麼我們必須將可讀字節與4進行比較? – Michael

+0

因爲一個int是4個字節長... –

+0

我看..非常感謝! – Michael

相關問題