副问题[/!--empirenews.page--]
接上篇《TCP 粘包和半包 先容及办理(上)》
上一篇先容了粘包和半包及其通用的办理方案,本日重点来看一下 Netty 是怎样实现封装成帧(Framing)方案的。

解码焦点流程
之前先容过三种解码器FixedLengthFrameDecoder、DelimiterBasedFrameDecoder、LengthFieldBasedFrameDecoder,它们都担任自ByteToMessageDecoder,而ByteToMessageDecoder担任自ChannelInboundHandlerAdapter,其焦点要领为channelRead。因此,我们来看看ByteToMessageDecoder的channelRead要领:
- @Override
- public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
- if (msg instanceof ByteBuf) {
- CodecOutputList out = CodecOutputList.newInstance();
- try {
- // 将传入的动静转化为data
- ByteBuf data = (ByteBuf) msg;
- // 最终实现的方针是将数据所有放进cumulation中
- first = cumulation == null;
- // 第一笔数据直接放入
- if (first) {
- cumulation = data;
- } else {
- // 不是第一笔数据就举办追加
- cumulation = cumulator.cumulate(ctx.alloc(), cumulation, data);
- }
- // 解码
- callDecode(ctx, cumulation, out);
- }
- // 以下代码省略,由于不属于解码进程
- }
再来看看callDecode要领:
- protected void callDecode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) {
- try {
- while (in.isReadable()) {
- int outoutSize = out.size();
- if (outSize > 0) {
- // 以下代码省略,由于初始状态时,outSize 只也许是0,不行能进入这里
- }
- int oldInputLength = in.readableBytes();
- // 在举办 decode 时,不执行handler的remove操纵。
- // 只有当 decode 执行完之后,开始整理数据。
- decodeRemovalReentryProtection(ctx, in, out);
- // 省略以下代码,由于后头的内容也不是解码的进程
再来看看decodeRemovalReentryProtection要领:
- final void decodeRemovalReentryProtection(ChannelHandlerContext ctx, ByteBuf in, List<Object> out)
- throws Exception {
- // 配置当前状态为正在解码
- decodeState = STATE_CALLING_CHILD_DECODE;
- try {
- // 解码
- decode(ctx, in, out);
- } finally {
- // 执行hander的remove操纵
- boolean removePending = decodeState == STATE_HANDLER_REMOVED_PENDING;
- decodeState = STATE_INIT;
- if (removePending) {
- handlerRemoved(ctx);
- }
- }
- }
- // 子类都重写了该要领,每种实现城市有本身非凡的解码方法
- protected abstract void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception;
从上面的进程可以总结出,在解码之前,必要先将数据写入cumulation,当解码竣事后,必要通过 handler 举办移除。
详细解码进程
方才说到decode要领在子类中都有实现,那针对我们说的三种解码方法,逐一看着实现。
1. FixedLengthFrameDecoder
其源码为:
- @Override
- protected final void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception {
- Object decodedecoded = decode(ctx, in);
- if (decoded != null) {
- out.add(decoded);
- }
- }
- protected Object decode(
- @SuppressWarnings("UnusedParameters") ChannelHandlerContext ctx, ByteBuf in) throws Exception {
- // 网络到的数据是否小于牢靠长度,小于就代表无法理会
- if (in.readableBytes() < frameLength) {
- return null;
- } else {
- return in.readRetainedSlice(frameLength);
- }
- }
就和这个类的名字一样简朴,就是牢靠长度举办解码,因此,在配置该解码器的时辰,必要在结构方法里传入frameLength。
2. DelimiterBasedFrameDecoder
(编辑:湖南网)
【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!
|