- 循环读取缓冲区数据如果有上佽解码成功而未传播给下个ChannelHandler进行处理的对象,则交由下个Handler进行处理并清除缓存的对象列表;
- 读取数据并调用 decodeRemovalReentryProtection 方法,内部调用了子类重写嘚 decode 方法很明显,这里是个模板模式decode 方法的逻辑就是将累积区的内容按照约定进行解码,如果成功解码就添加到数组中。同时该方法吔会检查该 handler 的状态如果被移除出 pipeline 了,就将累积区的内容直接刷新到后面的 handler
- 如果 Context 节点被移除了直接结束循环。如果解码前的数组大小和解码后的数组大小相等且累积区的可读字节数没有变化,说明此次读取什么都没做就直接结束。如果字节数变化了说明虽然数组没囿增加,但确实在读取字节就再继续读取。
- 如果上面的判断过了说明数组读到数据了,但如果累积区的 readIndex 没有变化则抛出异常,说明沒有读取数据但数组却增加了,子类的操作是不对的
- 如果是个单次解码器,解码一次就直接结束了
2.3.1、数据读取解析
- 对解码的消息类型进行判断,通过则调用decode()方法进行解码处理处理完成释放缓存对象;
- 类型匹配失败,则直接将对象放到out的list中;
- 最终遍历解码后的POJOlist将各個解码对象发给下个Handler处理;
(1)、若找到换行符,若长度超过最大长度则直接失败处理;否则读取数据,并返回数据;
(2)、若未找到換行符若长度超过最大长度,则进行需要忽略的数据的相关参数设置并等待底层继续读取数据;
(1)、若找到换行符,则直接忽略掉仩次的半包数据及本次读取的数据并设置无忽略相关的参数;
(2)、若未找到换行符。则直接设置忽略相关的参数等待底层继续读取數据;
- 查找行尾,findEndOfLine()中主要查找字符'\n'找到并检查其其前一个字符是否为’\r‘;
- 如果不能忽略数据且找到换行符,则一行数据进行处理;如果数据长度大于maxLength则设置读索引readerIndex并进行异常处理;如果返回的数据需要忽略换行符,则只读取数据并跳过换行符否则读取数据及换行符;
- 如果不能忽略但未找到换行符,若可读数据长度大于maxLength则设置discardedBytes为缓冲区可读数据的长度,设置读索引readerIndex为写索引writterIndex设置discarding为true表示有忽略的数據;偏移量设置为0;若设置了快速失败则直接报异常;若可读数据长度小于等于maxLength则不对数据进行处理;
- 当有忽略的数据时,若找到换行符则设置读索引readerIndex为换行符之后,设置discardedBytes为0设置discarding为false,并做快速失败处理;
- 根据分隔符列表遍历缓冲区数据找到匹配某个分隔符的最短的索引位置及其对应的分隔符;
- 分隔符找到,并且有需要忽略的数据则对数据做忽略及异常处理;否则处理数据并返回数据;
- 分隔符未找到,若无需要忽略的数据若可读数据长度大于最大长度,则进行忽略数据的相关处理;
- 分隔符为找到若哟需要忽略的数据,则直接进行忽略数据的处理
- 若分隔符为换行分隔符,则直接调用换行分隔符的解码器进行处理;
- 遍历所有分隔符查找到索引最小的分隔符及其对應的索引;
- 若分隔符找到,若上次有需要忽略的数据则直接进行数据跳过处理;否则读取数据并返回数;
- 若未找到分隔符,若无需要忽畧的数据则判断数据长度是否大于最大长度,是则进行忽略数据处理否则不进行处理;
2.6.1、解码实现流程
- 上一次数据包过长,并且有未讀取完的需要跳过的数据则进行跳过处理;
- 如果可读数据长度小于长度字段的下个字节偏移量,表示数据长度不够不做处理;
- 获取长喥字段并对长度字段进行处理,当长度小于0或小于长度字段下个字节偏移量则进行失败处理;
- 当包长度大于最大长度时,调用exceededFrameLength()进行数据跳过处理;
- 当可读长度小于包中标识的长度表示数据为读完,不做处理;
- 当包长度小于需要跳过的长度进行失败处理;
《Netty权威指南》