FrameDecoder介绍

FrameDecoder 负责 decodes the received ChannelBuffer s into a meaningful frame object.

In a stream-based transport such as TCP/IP, packets can be fragmented and reassembled during transmission even in a LAN environment. For example, let us assume you have received three packets:

 +-----+-----+-----+
 | ABC | DEF | GHI |
 +-----+-----+-----+
 

because of the packet fragmentation, a server can receive them like the following:

 +----+-------+---+---+
 | AB | CDEFG | H | I |
 +----+-------+---+---+
 

FrameDecoder   helps you defrag the received packets into one or more meaningful  frames   that could be easily understood by the application logic. In case of the example above, your  FrameDecoder   implementation could defrag the received packets like the following:

 +-----+-----+-----+
 | ABC | DEF | GHI |
 +-----+-----+-----+
 

The following code shows an example handler which decodes a frame whose first 4 bytes header represents the length of the frame, excluding the header.

 MESSAGE FORMAT
 ==============

 Offset:  0        4                   (Length + 4)
          +--------+------------------------+
 Fields:  | Length | Actual message content |
          +--------+------------------------+

 DECODER IMPLEMENTATION
 ======================

 public class IntegerHeaderFrameDecoder extends FrameDecoder {

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

     // Make sure if the length field was received.
     if (buf.readableBytes() < 4) {
        // The length field was not received yet - return null.
        // This method will be invoked again when more packets are
        // received and appended to the buffer.
        return null

;
     }

     // The length field is in the buffer.

     // Mark the current buffer position before reading the length field
     // because the whole frame might not be in the buffer yet.
     // We will reset the buffer position to the marked position if
     // there's not enough bytes in the buffer.
     buf.markReaderIndex();

     // Read the length field.
     int length = buf.readInt();

     // Make sure if there's enough bytes in the buffer.
     if (buf.readableBytes() < length) {
        // The whole bytes were not received yet - return null.
        // This method will be invoked again when more packets are
        // received and appended to the buffer.

        // Reset to the marked position to read the length field again
        // next time.
        buf.resetReaderIndex();

        return null

;
     }

     // There's enough bytes in the buffer. Read it.
     ChannelBuffer frame = buf.readBytes(length);

     // Successfully decoded a frame.  Return the decoded frame.
     return frame

;
   }
 }
 

Returning a POJO rather than a  ChannelBuffer

Please note that you can return an object of a different type than  ChannelBuffer   in your  decode()   and  decodeLast() implementation. For example, you could return a  POJO   so that the next  ChannelUpstreamHandler   receives a  MessageEvent which contains a POJO rather than a  ChannelBuffer .

Replacing a decoder with another decoder in a pipeline

If you are going to write a protocol multiplexer, you will probably want to replace a  FrameDecoder   (protocol detector) with another  FrameDecoder   or  ReplayingDecoder   (actual protocol decoder). It is not possible to achieve this simply by callingChannelPipeline.replace(ChannelHandler, String, ChannelHandler) , but some additional steps are required:

 public class FirstDecoder extends FrameDecoder {

     public FirstDecoder() {
         super(true); // Enable unfold
     }

     protected Object decode(ChannelHandlerContext ctx, Channel ch, ChannelBuffer buf) {
         ...
         // Decode the first message
         Object firstMessage = ...;

         // Add the second decoder
         ctx.getPipeline().addLast("second", new SecondDecoder());

         // Remove the first decoder (me)
         ctx.getPipeline().remove(this);

         if (buf.readable()) {
             // Hand off the remaining data to the second decoder
             return new Object[] { firstMessage, buf.readBytes(buf.readableBytes()) };
         } else {
             // Nothing to hand off
             return firstMessage;
         }
     }
 }

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值