netty 源码解析,netty 解码器
00-1010行解码器LineBasedFrameDecoder首先看它的参数。我们遵循重载解码方法。我们来看看findEndOfLine(buffer)方法。之前的门户:Netty分布式定长解码器实现原理分析
在本节中,我们将了解下行链路解码器LineBasedFrameDecoder。行解码器的作用是一个字节流,可以用rn解码,也可以直接用n结尾,即可以用newline解析。
类似地,这个解码器也继承了ByteToMessageDecoder
目录
00-1010//数据包的最大长度,超过该长度将执行丢弃模式private final int maxLength//超过最大长度。是否要抛出异常private final boolean failFast//最终解析的包是否有换行符私有最终布尔条带分隔符;//true表示当前解码过程是丢弃模式私有布尔丢弃;//丢弃多少字节的private int discardedBytes其中,丢弃模式,我们会在源代码中看到含义。
让我们看看它的解码方法。
受保护的最终void decode(ChannelHandlerContext CTX,ByteBuf in,ListObject out)抛出异常{ Object decode=decode(CTX,in);如果(解码!=null) { out.add(解码);}}}这里的解码方法和我们上一节分析的解码方法是一样的。它调用重载的decode方法,并将解码后的内容放入out集合。
00-1010保护对象解码(通道处理程序上下文CTX,byte buf缓冲区)抛出异常{//找到这一行的结尾,final int eol=findendorfline(buffer);如果(!丢弃){ if (eol=0) {最终字节缓冲帧;//计算从新行到可读字节的长度,final int length=eol-buffer . reader index();//获取分隔符长度。rn如果是结尾,分隔符长度为2 final int delimlength=buffer . get byte(eol)== r ?2 : 1;//如果长度大于最大长度if (length maxLength) {//指向换行符后的可读字节(这段数据完全丢弃)buffer . reader index(eoldelimlength);//传播异常事件fail(ctx,length);返回null}//如果本次解析的数据有效//分隔符是否计入完整数据包//true为丢弃分隔符if (stripDelimiter) {//Intercept有效长度frame=buffer . read retained slice(length);//跳过分隔符的byte buffer . Skip bytes(delimLength);} else {//包含分隔符frame=buffer . readretentedslice(length delimlength);}返回框架;} else {//如果没有找到分隔符(非丢弃模式)//可读字节长度最终为int length=buffer . readable bytes();
//如果朝超过能解析的最大长度 if (length > maxLength) { //将当前长度标记为可丢弃的 discardedBytes = length; //直接将读指针移动到写指针 buffer.readerIndex(buffer.writerIndex()); //标记为丢弃模式 discarding = true; //超过最大长度抛出异常 if (failFast) { fail(ctx, "over " + discardedBytes); } } //没有超过, 则直接返回 return null; } } else { //丢弃模式 if (eol >= 0) { //找到分隔符 //当前丢弃的字节(前面已经丢弃的+现在丢弃的位置-写指针) final int length = discardedBytes + eol - buffer.readerIndex(); //当前换行符长度为多少 final int delimLength = buffer.getByte(eol) == r? 2 : 1; //读指针直接移到换行符+换行符的长度 buffer.readerIndex(eol + delimLength); //当前丢弃的字节为0 discardedBytes = 0; //设置为未丢弃模式 discarding = false; //丢弃完字节之后触发异常 if (!failFast) { fail(ctx, length); } } else { //累计已丢弃的字节个数+当前可读的长度 discardedBytes += buffer.readableBytes(); //移动 buffer.readerIndex(buffer.writerIndex()); } return null; }}
finalinteol = findEndOfLine(buffer)
这里是找当前行的结尾的索引值, 也就是rn或者是n:
6-3-1
图中不难看出, 如果是以n结尾的, 返回的索引值是n的索引值, 如果是rn结尾的, 返回的索引值是r的索引值
我们看findEndOfLine(buffer)方法
private static int findEndOfLine(final ByteBuf buffer) { //找到/n这个字节 int i = buffer.forEachByte(ByteProcessor.FIND_LF); //如果找到了, 并且前面的字符是-r, 则指向/r字节 if (i > 0 && buffer.getByte(i - 1) == r) { i--; } return i;}
这里通过一个forEachByte方法找n这个字节, 如果找到了, 并且前面是r, 则返回r的索引, 否则返回n的索引
回到重载的decode方法中:
if(!discarding)判断是否为非丢弃模式, 默认是就是非丢弃模式, 所以进入if中
if(eol >= 0)如果找到了换行符, 我们看非丢弃模式下找到换行符的相关逻辑:
final ByteBuf frame; final int length = eol - buffer.readerIndex();final int delimLength = buffer.getByte(eol) == r? 2 : 1; if (length > maxLength) { buffer.readerIndex(eol + delimLength); fail(ctx, length); return null;} if (stripDelimiter) { frame = buffer.readRetainedSlice(length); buffer.skipBytes(delimLength);} else { frame = buffer.readRetainedSlice(length + delimLength);}return frame;
首先获得换行符到可读字节之间的长度, 然后拿到换行符的长度, 如果是n结尾, 那么长度为1, 如果是r结尾, 长度为2
if(length > maxLength)带表如果长度超过最大长度, 则直接通过readerIndex(eol + delimLength)这种方式, 将读指针指向换行符之后的字节, 说明换行符之前的字节需要完全丢弃
6-3-2
丢弃之后通过fail方法传播异常, 并返回null
继续往下看, 走到下一步, 说明解析出来的数据长度没有超过最大长度, 说明是有效数据包
if(stripDelimiter)表示是否要将分隔符放在完整数据包里面, 如果是true, 则说明要丢弃分隔符, 然后截取有效长度, 并跳过分隔符长度
将包含分隔符进行截取
以上就是非丢弃模式下找到换行符的相关逻辑
我们再看非丢弃模式下没有找到换行符的相关逻辑, 也就是非丢弃模式下, if(eol >= 0)中的else块:
final int length = buffer.readableBytes();if (length > maxLength) { discardedBytes = length; buffer.readerIndex(buffer.writerIndex()); discarding = true; if (failFast) { fail(ctx, "over " + discardedBytes); }} return null;
首先通过finalintlength = buffer.readableBytes()获取所有的可读字节数
然后判断可读字节数是否超过了最大值, 如果超过最大值, 则属性discardedBytes标记为这个长度, 代表这段内容要进行丢弃
6-3-3
buffer.readerIndex(buffer.writerIndex())这里直接将读指针移动到写指针, 并且将discarding设置为true, 就是丢弃模式
如果可读字节没有超过最大长度, 则返回null, 表示什么都没解析出来, 等着下次解析
我们再看丢弃模式的处理逻辑, 也就是if(!discarding)中的else块:
首先这里也分两种情况, 根据if(eol >= 0)判断是否找到了分隔符, 我们首先看找到分隔符的解码逻辑:
final int length = discardedBytes + eol - buffer.readerIndex();final int delimLength = buffer.getByte(eol) == r? 2 : 1;buffer.readerIndex(eol + delimLength);discardedBytes = 0;discarding = false;if (!failFast) { fail(ctx, length);}
如果找到换行符, 则需要将换行符之前的数据全部丢弃掉
6-3-4
finalintlength = discardedBytes + eol - buffer.readerIndex()
这里获得丢弃的字节总数, 也就是之前丢弃的字节数+现在需要丢弃的字节数
然后计算换行符的长度, 如果是n则是1, rn就是2
buffer.readerIndex(eol + delimLength)
这里将读指针移动到换行符之后的位置
然后将discarding设置为false, 表示当前是非丢弃状态
我们再看丢弃模式未找到换行符的情况, 也就是丢弃模式下, if(eol >= 0)中的else块:
discardedBytes += buffer.readableBytes();buffer.readerIndex(buffer.writerIndex());
这里做的事情非常简单, 就是累计丢弃的字节数, 并将读指针移动到写指针, 也就是将数据全部丢弃
最后在丢弃模式下, decode方法返回null, 代表本次没有解析出任何数据
以上就是行解码器的相关逻辑
以上就是Netty分布式行解码器逻辑源码解析的详细内容,更多关于Netty分布式行解码器的资料请关注盛行IT其它相关文章!
郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。