概要
顧名思義, 基于換行符的解碼器.
關(guān)鍵屬性
/** Maximum length of a frame we're willing to decode. */
private final int maxLength;
/** Whether or not to throw an exception as soon as we exceed maxLength. */
private final boolean failFast;
private final boolean stripDelimiter;
/** True if we're discarding input because we're already over maxLength. */
private boolean discarding;
private int discardedBytes;
解碼
protected Object decode(ChannelHandlerContext ctx, ByteBuf buffer) throws Exception {
// 查找buffer中的換行符
final int eol = findEndOfLine(buffer);
// 如果是非丟棄模式,說(shuō)明一切正常
if (!discarding) {
// 如果有換行符
if (eol >= 0) {
final ByteBuf frame;
// 那么readerindex-eol之間是可讀的范圍
final int length = eol - buffer.readerIndex();
final int delimLength = buffer.getByte(eol) == '\r'? 2 : 1;
// 如果可讀的范圍超過(guò)了最大閾值,那么跳過(guò)這段
if (length > maxLength) {
// 直接跳到該換行符之后
buffer.readerIndex(eol + delimLength);
// 而且還要傳遞異常TooLongFrameException
fail(ctx, length);
return null;
}
// 最終讀取的數(shù)據(jù)中是否要包含換行符
if (stripDelimiter) {
frame = buffer.readRetainedSlice(length);
buffer.skipBytes(delimLength);
} else {
frame = buffer.readRetainedSlice(length + delimLength);
}
return frame;
// 如果沒(méi)有找到換行符
} else {
final int length = buffer.readableBytes();
// 且可讀的范圍超過(guò)了最大閾值,那么直接跳過(guò)這段
if (length > maxLength) {
discardedBytes = length;
// 將readerindex移動(dòng)到writerindex,表示這一段數(shù)據(jù)全部丟棄
buffer.readerIndex(buffer.writerIndex());
// 進(jìn)入丟棄模式
discarding = true;
if (failFast) {
fail(ctx, "over " + discardedBytes);
}
}
return null;
}
// 如果是丟棄模式
} else {
// 如果發(fā)現(xiàn)換行符, 那么這一段直接丟棄
if (eol >= 0) {
// 計(jì)算總共丟棄了多少長(zhǎng)度
final int length = discardedBytes + eol - buffer.readerIndex();
final int delimLength = buffer.getByte(eol) == '\r'? 2 : 1;
// 直接跳到換行符之后, 重新開(kāi)始新一輪讀取
buffer.readerIndex(eol + delimLength);
// 丟棄模式轉(zhuǎn)正常模式
discardedBytes = 0;
discarding = false;
// 報(bào)警
if (!failFast) {
fail(ctx, length);
}
// 如果還沒(méi)有找到換行符, 那么這次的全部丟棄, 繼續(xù)讀取
} else {
discardedBytes += buffer.readableBytes();
buffer.readerIndex(buffer.writerIndex());
}
return null;
}
}
總體很簡(jiǎn)單, 主要是maxLength在里面作祟, 理解為數(shù)據(jù)通過(guò)換行符切分, 每一段都必須在maxLength范圍內(nèi), 否則整段丟棄.