给定足够的数据,这个实现将产生固定大小的帧。如果没有足够的数据可供读取,它将等待下一个数据块的到来,并将再次检查 是否能够产生一个新的帧。
这个特定的解 码器将产生固定为 3 字节大小的帧。因此,它可能会需要多个事件来提供足够的字节数以产生一个帧。

FixedLengthFrameDecoderTest

  1. package cn.enjoyedu.nettybasic.embedded;
  2. import io.netty.buffer.ByteBuf;
  3. import io.netty.buffer.Unpooled;
  4. import io.netty.channel.embedded.EmbeddedChannel;
  5. import org.junit.Test;
  6. import static org.junit.Assert.*;
  7. /**
  8. * 作者:Mark/Maoke
  9. * 创建日期:2018/08/26
  10. * 类说明:测试入站
  11. */
  12. public class FixedLengthFrameDecoderTest {
  13. @Test
  14. public void testFramesDecoded() {
  15. //创建一个 ByteBuf,并存储 9 字节
  16. ByteBuf buf = Unpooled.buffer();
  17. for (int i = 0; i < 9; i++) {
  18. buf.writeByte(i);
  19. }
  20. ByteBuf input = buf.duplicate();
  21. EmbeddedChannel channel = new EmbeddedChannel(
  22. new FixedLengthFrameDecoder(3)
  23. );
  24. /*返回false*/
  25. assertFalse(channel.writeInbound(input.readBytes(1)));
  26. assertFalse(channel.writeInbound(input.readBytes(1)));
  27. assertTrue(channel.writeInbound(input.readBytes(1)));
  28. assertTrue(channel.writeInbound(input.readBytes(6)));
  29. channel.finish();
  30. // read messages
  31. //读取所生成的消息,并且验证是否有 3 帧(切片),其中每帧(切片)都为 3 字节
  32. ByteBuf read = (ByteBuf) channel.readInbound();
  33. //和源进行比对
  34. assertEquals(buf.readSlice(3), read);
  35. read.release();
  36. read = (ByteBuf) channel.readInbound();
  37. assertEquals(buf.readSlice(3), read);
  38. read.release();
  39. read = (ByteBuf) channel.readInbound();
  40. assertEquals(buf.readSlice(3), read);
  41. read.release();
  42. assertNull(channel.readInbound());
  43. buf.release();
  44. }
  45. }

FixedLengthFrameDecoder

  1. package cn.enjoyedu.nettybasic.embedded;
  2. import io.netty.buffer.ByteBuf;
  3. import io.netty.channel.ChannelHandlerContext;
  4. import io.netty.handler.codec.ByteToMessageDecoder;
  5. import java.util.List;
  6. /**
  7. * FixedLengthFrameDecoder
  8. */
  9. //扩展 ByteToMessageDecoder 以处理入站字节,并将它们解码为消息
  10. public class FixedLengthFrameDecoder extends ByteToMessageDecoder {
  11. private final int frameLength;
  12. //指定要生成的帧的长度
  13. public FixedLengthFrameDecoder(int frameLength) {
  14. if (frameLength <= 0) {
  15. throw new IllegalArgumentException(
  16. "frameLength must be a positive integer: " + frameLength);
  17. }
  18. this.frameLength = frameLength;
  19. }
  20. @Override
  21. protected void decode(ChannelHandlerContext ctx, ByteBuf in,
  22. List<Object> out) throws Exception {
  23. //检查是否有足够的字节可以被读取,以生成下一个帧
  24. while (in.readableBytes() >= frameLength) {
  25. //从 ByteBuf 中读取一个新帧
  26. ByteBuf buf = in.readBytes(frameLength);
  27. //将该帧添加到已被解码的消息列表中
  28. out.add(buf);
  29. }
  30. }
  31. }