给定足够的数据,这个实现将产生固定大小的帧。如果没有足够的数据可供读取,它将等待下一个数据块的到来,并将再次检查 是否能够产生一个新的帧。
这个特定的解 码器将产生固定为 3 字节大小的帧。因此,它可能会需要多个事件来提供足够的字节数以产生一个帧。
FixedLengthFrameDecoderTest
package cn.enjoyedu.nettybasic.embedded;import io.netty.buffer.ByteBuf;import io.netty.buffer.Unpooled;import io.netty.channel.embedded.EmbeddedChannel;import org.junit.Test;import static org.junit.Assert.*;/*** 作者:Mark/Maoke* 创建日期:2018/08/26* 类说明:测试入站*/public class FixedLengthFrameDecoderTest {@Testpublic void testFramesDecoded() {//创建一个 ByteBuf,并存储 9 字节ByteBuf buf = Unpooled.buffer();for (int i = 0; i < 9; i++) {buf.writeByte(i);}ByteBuf input = buf.duplicate();EmbeddedChannel channel = new EmbeddedChannel(new FixedLengthFrameDecoder(3));/*返回false*/assertFalse(channel.writeInbound(input.readBytes(1)));assertFalse(channel.writeInbound(input.readBytes(1)));assertTrue(channel.writeInbound(input.readBytes(1)));assertTrue(channel.writeInbound(input.readBytes(6)));channel.finish();// read messages//读取所生成的消息,并且验证是否有 3 帧(切片),其中每帧(切片)都为 3 字节ByteBuf read = (ByteBuf) channel.readInbound();//和源进行比对assertEquals(buf.readSlice(3), read);read.release();read = (ByteBuf) channel.readInbound();assertEquals(buf.readSlice(3), read);read.release();read = (ByteBuf) channel.readInbound();assertEquals(buf.readSlice(3), read);read.release();assertNull(channel.readInbound());buf.release();}}
FixedLengthFrameDecoder
package cn.enjoyedu.nettybasic.embedded;import io.netty.buffer.ByteBuf;import io.netty.channel.ChannelHandlerContext;import io.netty.handler.codec.ByteToMessageDecoder;import java.util.List;/*** FixedLengthFrameDecoder*///扩展 ByteToMessageDecoder 以处理入站字节,并将它们解码为消息public class FixedLengthFrameDecoder extends ByteToMessageDecoder {private final int frameLength;//指定要生成的帧的长度public FixedLengthFrameDecoder(int frameLength) {if (frameLength <= 0) {throw new IllegalArgumentException("frameLength must be a positive integer: " + frameLength);}this.frameLength = frameLength;}@Overrideprotected void decode(ChannelHandlerContext ctx, ByteBuf in,List<Object> out) throws Exception {//检查是否有足够的字节可以被读取,以生成下一个帧while (in.readableBytes() >= frameLength) {//从 ByteBuf 中读取一个新帧ByteBuf buf = in.readBytes(frameLength);//将该帧添加到已被解码的消息列表中out.add(buf);}}}
