Netty inside will use a piece of buffer to provide data for you when you read data from channel.
The size of buffer is dynamic. Netty will change the size of buffer in this way:
1.the initial size would be small.
2.every time after you read the channel (means you read data from buffer),netty records the
size of readable bytes in the buffer
3.if the size of readable bytes is less that the value of last time, netty would do nothing with
the size of the buffer, because netty think you have read all data you need, and wait you
reading again;
4.if the size of readable bytes equals to the value of last time, netty would enlarge the size of
the buffer and fill it with data, because netty notices that you have the chance to read the data
but you didn't read data, netty guess you want more data, so netty enlarge the buffer and fill
with more fresh data.
So, what you would actually do is not to read from the buffer if the
readableBytes is less than you want.
there are two scenarios:
1) the size of the data you want is a constant value:
In this scenario, you just compare the readableBytes to the constant
value. if the data is not enough, you do nothing, just return; if the data
is enough, you read it and do what you want
2)the size of the data you want is encoded in the fist several bytes of data( just as many
protocal)
you can use FixedLengthFrameDecoder to do the stuff.
if FixedLengthFrameDecoder is not satisfied you, you can do some thing like that when
reading the channel:
a)mark the reader index
b)read the first several bytes, and calculate the length of the data you want
c)if the readableBytes is enough, read it and do what you want
d)if the readableBytes is not enough, reset the reader index(to tell netty that you don't read the data)
Talk is cheap, show you code.
A way to handle this is to use ByteToMessageDecoder.
Extend it and override ByteToMessageDecoder's decode method.
To solve scenario 1):
@Override
protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception {
int LENGTH = 200000;
if (in.readableBytes() < LENGTH)
return;
else {
byte[] bytes = new byte[LENGTH];
in.readBytes(bytes , 0, LENGTH);
//do stuff...
}
}
To solve scenario 2):
@Override
protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception {
int LENGTH_SIZE = 4;
byte[] lengthBytes = new byte[LENGTH_SIZE ];
in.markReaderIndex().readBytes(lengthBytes, 0, LENGTH_SIZE );
int length = Bits.toInt(lengthBytes);
if (in.readableBytes() >= length) {
byte[] content = new byte[length];
in.readBytes(content, 0, length);
//do some stuff
} else {
in.resetReaderIndex();
}
}