给定足够的数据,这个实现将产生固定大小的帧。如果没有足够的数据可供读取,它将等待下一个数据块的到来,并将再次检查 是否能够产生一个新的帧。
这个特定的解 码器将产生固定为 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 {
@Test
public 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;
}
@Override
protected void decode(ChannelHandlerContext ctx, ByteBuf in,
List<Object> out) throws Exception {
//检查是否有足够的字节可以被读取,以生成下一个帧
while (in.readableBytes() >= frameLength) {
//从 ByteBuf 中读取一个新帧
ByteBuf buf = in.readBytes(frameLength);
//将该帧添加到已被解码的消息列表中
out.add(buf);
}
}
}