2013-03-12 109 views
1

我已经为我正在构建的应用程序实现了一个帧解码器。到目前为止,当我运行代码时,数据包被很好地解码,我可以看到接收到的数据包并且是正确的。但是我得到一个异常:Netty Framedecoder错误

decode() method must read at least one byte if it returned a frame (caused by: class com.smsgh.unitysmpp.Plugins.Smp.SmpPduFrameDecoder) 
    at org.jboss.netty.handler.codec.frame.FrameDecoder.callDecode(FrameDecoder.java:434) 
    at org.jboss.netty.handler.codec.frame.FrameDecoder.messageReceived(FrameDecoder.java:303) 
    at org.jboss.netty.channel.Channels.fireMessageReceived(Channels.java:268) 
    at org.jboss.netty.channel.Channels.fireMessageReceived(Channels.java:255) 
    at org.jboss.netty.channel.socket.nio.NioWorker.read(NioWorker.java:84) 
    at org.jboss.netty.channel.socket.nio.AbstractNioWorker.processSelectedKeys(AbstractNioWorker.java:471) 
    at org.jboss.netty.channel.socket.nio.AbstractNioWorker.run(AbstractNioWorker.java:332) 
    at org.jboss.netty.channel.socket.nio.NioWorker.run(NioWorker.java:35) 
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1110) 
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:603) 

这是我写的代码: /** * @author温格 * */

public class SmpPduFrameDecoder extends FrameDecoder { 

    private static Logger logger = LoggerFactory.getLogger(SmpPduFrameDecoder.class); 


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

     ChannelBuffer leFrame = null; 
     // Check the Endianness of the packet sent 
     if(buffer.order() == ByteOrder.BIG_ENDIAN){ 
      if(buffer.hasArray()){ 
       leFrame = ChannelBuffers.wrappedBuffer(ByteOrder.LITTLE_ENDIAN, buffer.array(), buffer.arrayOffset(), buffer.capacity()); 
      } 
      else{ 
       leFrame = ChannelBuffers.wrappedBuffer(buffer.toByteBuffer().order(ByteOrder.LITTLE_ENDIAN)); 
      } 
     } 

     // Read the byte length 
     // wait until the length prefix is available 
     if (leFrame.readableBytes() < 4) { 
      logger.debug("Unable to Read the Length"); 
      return null; 
     } 

     // parse the frame length (first 4 bytes) 
     int frameLength = leFrame.getInt(leFrame.readerIndex()); 
     logger.info("Packet Received Length " + frameLength); 

     // wait until the whole data is available 
     if (leFrame.readableBytes() < frameLength) { 
      logger.debug("Unable to read the full PDU received"); 
      return null; 
     } 

     leFrame.skipBytes(4); 

     int readerIndex = leFrame.readerIndex(); 
     ChannelBuffer frame = leFrame.readBytes(frameLength);  
     leFrame.readerIndex(readerIndex+frameLength); 

     byte[] byteArray = frame.array(); 
     StringBuilder sb = new StringBuilder(); 
     for(byte b : byteArray){ 
      sb.append(HexUtil.toHexString(b)); 
     } 
     logger.info("Decode Frame Received without the length " +sb.toString());   
     logger.debug("Full PDU has been read"); 
     return frame; 
    } 
} 

谁能告诉我什么是错eith我的代码并帮助我解决这个异常?

回答

1

我已经解决了这个问题。代替将缓冲区复制到新缓冲区中,我只需使用swapInt来获得实际的帧长度,如下所示:

public class SmpPduFrameDecoder extends FrameDecoder { 

    private static Logger logger = LoggerFactory.getLogger(SmpPduFrameDecoder.class); 


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

     // Read the byte length 
     // wait until the length prefix is available 
     if (buffer.readableBytes() < 4) { 
      logger.debug("Unable to Read the Length"); 
      return null; 
     } 

     // parse the frame length (first 4 bytes) 
     //int frameLength = leFrame.getInt(leFrame.readerIndex()); 
     int frameLength = ChannelBuffers.swapInt(buffer.getInt(buffer.readerIndex())); 
     logger.info("Packet Received Length " + frameLength); 

     // wait until the whole data is available 
     if (buffer.readableBytes() < frameLength) { 
      logger.debug("Unable to read the full PDU received"); 
      return null; 
     } 

     buffer.skipBytes(4); 
     ChannelBuffer frame = buffer.readBytes(frameLength); 
     buffer.readerIndex(frameLength + 4); 

     byte[] byteArray = frame.array(); 
     StringBuilder sb = new StringBuilder(); 
     for(byte b : byteArray){ 
      sb.append(HexUtil.toHexString(b)); 
     } 
     logger.info("Decode Frame Received without the length " +sb.toString());   
     logger.debug("Full PDU has been read"); 
     return frame; 
    } 
}