2013-01-16 87 views
2

我目前正在評估Netty來處理Java客戶端與C++服務器集成的套接字通信。消息傳遞協議具有以下結構 -從LengthFieldBasedFrameDecoder返回的緩衝區太小

  • (類型)(亞型)(長度)(消息體)與大小
  • < 4字節> < 4字節> < 4字節> < ...> - 長度包括標題。

繼Netty api後,我繼承了LengthFieldBasedFrameDecoder來接收一個有效的完整數據包,然後根據接收的類型解碼每個數據包。從文檔我使用 -

  • lengthFieldOffset = 8
  • lengthFieldLength = 4
  • lengthAdjustment = -12(= HDR1 + LEN的長度,負)
  • initialBytesToStrip = 0

它工作正常約5分鐘(我收到一個消息,每5秒左右),然後解碼事件包含一個比消息的大小短得多的ChannelBuffer。 (我在崩潰前多次收到此消息)。然後我顯然在我的內部解碼代碼中得到了一個BufferUnderflowException。難道我做錯了什麼?在使用LengthFieldBasedFrameDecoder時,我應該保證消息的正確大小的緩衝區?

LengthFieldBasedFrameDecoder類 -

public class CisPacketDecoder extends LengthFieldBasedFrameDecoder 
{ 
    public CisPacketDecoder(int maxFrameLength, int lengthFieldOffset, 
      int lengthFieldLength, int lengthAdjustment, int initialBytesToStrip) { 
     super(maxFrameLength, lengthFieldOffset, lengthFieldLength, lengthAdjustment, 
       initialBytesToStrip);  
    } 

    @Override 
    protected Object decode(ChannelHandlerContext ctx, Channel channel, ChannelBuffer buf) 
      throws Exception 
    {  
     CisMessage message = null;  
     int type = buf.getInt(0); //Type is always first int 
     CisMessageType messageType = CisMessageType.fromIntToType(type); 
     if(messageType != null) 
     { 
      message = messageType.getObject(); 
      if(message != null) 
      { 
       message.decode(buf.toByteBuffer()); 
      } 
      else 
      { 
       System.out.println("Unable to create message for type " + type); 
      } 
     } 

     //mark the Channel buf as read by moving reader index 
     buf.readerIndex(buf.capacity()); 
     return message; 
    } 

} 

這裏實例化。

public class PmcPipelineFactory implements ChannelPipelineFactory 
{ 

    @Override 
    public ChannelPipeline getPipeline() throws Exception 
    { 
     ChannelPipeline pipeline = Channels.pipeline(); 

     pipeline.addLast("encoder", new CisPacketEncoder()); 
     pipeline.addLast("decoder", new CisPacketDecoder(1024, 8, 4, -12, 0));  
     pipeline.addLast("handler", new MsgClientHandler()); 
     return pipeline; 
    } 


} 

回答

2

您需要調用super.decode(..)並在解碼(..)方法中對返回的ChannelBuffer進行操作。

所以它會是這樣的;

public class CisPacketDecoder extends LengthFieldBasedFrameDecoder { 
    public CisPacketDecoder(int maxFrameLength, int lengthFieldOffset, 
      int lengthFieldLength, int lengthAdjustment, int initialBytesToStrip) { 
     super(maxFrameLength, lengthFieldOffset, lengthFieldLength, lengthAdjustment, 
      initialBytesToStrip);  
    } 

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

     // THIS IS IMPORTANT!!!!! 
     ChannelBuffer decoded = (ChannelBuffer) super.decode(ctx, channel, buf); 
     if (decoded == null) { 
      return null; 
     } 

     // NOW ONLY OPERATE ON decoded 
     CisMessage message = null;  
     int type = decoded.getInt(0); //Type is always first int 
     CisMessageType messageType = CisMessageType.fromIntToType(type); 
     if(messageType != null) { 
      message = messageType.getObject(); 
      if(message != null) { 
       message.decode(decoded.toByteBuffer()); 
      } else { 
       System.out.println("Unable to create message for type " + type); 
      } 
     } 
     return message; 
    } 
} 

一定要檢查大寫意見。

+0

非常感謝,現在一切正常。不要以爲我會自己找到一個! – ChillyMc