DelimiterBasedFrameDecoder自定義分隔符解碼器
package io.netty.handler.codec;
import static io.netty.util.internal.ObjectUtil.checkPositive;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import java.util.List;
//自定義分隔符解碼器
public class DelimiterBasedFrameDecoder extends ByteToMessageDecoder {
//自定義的分隔符,可以使用多個
private final ByteBuf[] delimiters;
//每個消息段落最大長度
private final int maxFrameLength;
//解碼消息時,是否丟棄分隔符
private final boolean stripDelimiter;
//遇到錯誤時,是否拋出異常
private final boolean failFast;
//狀態變量-是否正在丟棄一個段的消息
private boolean discardingTooLongFrame;
//丟棄總長度
private int tooLongFrameLength;
//\r\n的解碼器
private final LineBasedFrameDecoder lineBasedDecoder;
public DelimiterBasedFrameDecoder(
int maxFrameLength, boolean stripDelimiter, boolean failFast, ByteBuf... delimiters) {
validateMaxFrameLength(maxFrameLength);
if (delimiters == null) {
throw new NullPointerException("delimiters");
}
if (delimiters.length == 0) {
throw new IllegalArgumentException("empty delimiters");
}
//delimiters裏的分隔符 是否是\r\n
if (isLineBased(delimiters) && !isSubclass()) {
lineBasedDecoder = new LineBasedFrameDecoder(maxFrameLength, stripDelimiter, failFast);
this.delimiters = null;
} else {
//創建數組
this.delimiters = new ByteBuf[delimiters.length];
for (int i = 0; i < delimiters.length; i ++) {
ByteBuf d = delimiters[i];
validateDelimiter(d);
//創建d的分區放入數組
this.delimiters[i] = d.slice(d.readerIndex(), d.readableBytes());
}
lineBasedDecoder = null;
}
this.maxFrameLength = maxFrameLength;
this.stripDelimiter = stripDelimiter;
this.failFast = failFast;
}
//判斷是否是Delimiters.lineDelimiter()
/** Returns true if the delimiters are "\n" and "\r\n". */
private static boolean isLineBased(final ByteBuf[] delimiters) {
if (delimiters.length != 2) {
return false;
}
ByteBuf a = delimiters[0];
ByteBuf b = delimiters[1];
if (a.capacity() < b.capacity()) {
a = delimiters[1];
b = delimiters[0];
}
return a.capacity() == 2 && b.capacity() == 1
&& a.getByte(0) == '\r' && a.getByte(1) == '\n'
&& b.getByte(0) == '\n';
}
//判斷是否是子類
private boolean isSubclass() {
return getClass() != DelimiterBasedFrameDecoder.class;
}
@Override
protected final void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception {
Object decoded = decode(ctx, in);
if (decoded != null) {
out.add(decoded);
}
}
protected Object decode(ChannelHandlerContext ctx, ByteBuf buffer) throws Exception {
//如果分隔符是\r\n則用lineBasedDecoder解碼器解析
//此類就相當於lineBasedDecoder
if (lineBasedDecoder != null) {
return lineBasedDecoder.decode(ctx, buffer);
}
int minFrameLength = Integer.MAX_VALUE;
ByteBuf minDelim = null;
//循環所有分隔符,挨個去匹配
for (ByteBuf delim: delimiters) {
//匹配分隔符的起始位置
int frameLength = indexOf(buffer, delim);
//大於0,並且小於int最大值 說明匹配成功
if (frameLength >= 0 && frameLength < minFrameLength) {
minFrameLength = frameLength;
minDelim = delim;
}
}
//說明匹配成功
if (minDelim != null) {
//分隔符的capacity就代表了分隔符的長度
int minDelimLength = minDelim.capacity();
ByteBuf frame;
//如果之前已經開始丟棄字節
if (discardingTooLongFrame) {
// We've just finished discarding a very large frame.
// Go back to the initial state.
//恢復標記位
discardingTooLongFrame = false;
//跳過minFrameLength+分隔符的長度,表示丟棄了前一個完整的消息
buffer.skipBytes(minFrameLength + minDelimLength);
//丟棄的字節總數
int tooLongFrameLength = this.tooLongFrameLength;
this.tooLongFrameLength = 0;
if (!failFast) {
fail(tooLongFrameLength);
}
return null;
}
//消息長度大於閾值
if (minFrameLength > maxFrameLength) {
// Discard read frame.
//丟棄一個消息
buffer.skipBytes(minFrameLength + minDelimLength);
fail(minFrameLength);
return null;
}
//丟棄分隔符
if (stripDelimiter) {
//返回一個消息frame
frame = buffer.readRetainedSlice(minFrameLength);
//丟棄分隔符
buffer.skipBytes(minDelimLength);
} else {
//返回一個消息,包括了分隔符
frame = buffer.readRetainedSlice(minFrameLength + minDelimLength);
}
return frame;
} else { //沒找到分隔符的位置
//正常情況
if (!discardingTooLongFrame) {
//如果可讀字節大於最大長度限制
if (buffer.readableBytes() > maxFrameLength) {
// Discard the content of the buffer until a delimiter is found.
tooLongFrameLength = buffer.readableBytes();
//丟棄字節
buffer.skipBytes(buffer.readableBytes());
//標記丟棄狀態
discardingTooLongFrame = true;
if (failFast) {
fail(tooLongFrameLength);
}
}
} else {
//之前discardingTooLongFrame已經設置爲true
// Still discarding the buffer since a delimiter is not found.
//增加總丟棄數量
tooLongFrameLength += buffer.readableBytes();
//繼續丟棄字節
buffer.skipBytes(buffer.readableBytes());
}
return null;
}
}
private void fail(long frameLength) {
if (frameLength > 0) {
throw new TooLongFrameException(
"frame length exceeds " + maxFrameLength +
": " + frameLength + " - discarded");
} else {
throw new TooLongFrameException(
"frame length exceeds " + maxFrameLength +
" - discarding");
}
}
private static int indexOf(ByteBuf haystack, ByteBuf needle) {
//循環輸入的字節流緩衝區,假設 a b c d e
for (int i = haystack.readerIndex(); i < haystack.writerIndex(); i ++) {
//從[a] 0位置開始找
int haystackIndex = i;
int needleIndex;
//循環分隔符
for (needleIndex = 0; needleIndex < needle.capacity(); needleIndex ++) {
//如果分隔符與haystack.getByte(haystackIndex)不同,則結束當前循環
//haystack.getByte(haystackIndex) 從b開始繼續查詢
if (haystack.getByte(haystackIndex) != needle.getByte(needleIndex)) {
break;
} else {
haystackIndex ++;
//依次拿出bcde進行匹配,如果輸入緩衝區到達末尾,並且分隔符緩衝區還沒有到達末尾,說明匹配失敗
if (haystackIndex == haystack.writerIndex() &&
needleIndex != needle.capacity() - 1) {
return -1;
}
}
}
//如果分隔符緩衝區達到末尾,還沒發生上面的情況,說明匹配到了
if (needleIndex == needle.capacity()) {
// Found the needle from the haystack!
//i減去haystack.readerIndex()的位置就是分隔符的位置
return i - haystack.readerIndex();
}
}
return -1;
}
}