`
eyesmore
  • 浏览: 378244 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

CumulativeProtocolDecoder 流与事件模型

    博客分类:
  • MINA
阅读更多

 

ByteBuffer 的 flip 方法,许多人都知道是写操作后,即将要开始读操作,需要flip一把。但是,compact方法,知道的人似乎比较少,它用在什么场景呢?本文就是回答这个问题的。

 

import java.nio.ByteBuffer;

public class T {

	public static void main(String[] args) {
		ByteBuffer buf = ByteBuffer.allocate(8);
		buf.put((byte)0x00);
		buf.put((byte)0x01);
		buf.put((byte)0x02);
		buf.put((byte)0x03);
		System.out.println("连续写入4个:");
		System.out.println("\t"+buf);
		buf.flip();
		System.out.println("Flip后:");
		System.out.println("\t"+buf);
		byte b0 = buf.get();
		byte b1 = buf.get();
		System.out.println("连续读出2个:"+b0+" "+b1);
		System.out.println("\t"+buf);
		buf.compact();
		System.out.println("Compact后:(应用场景:上一次读没完,下一次写就开始了)");
		System.out.println("\t"+buf);
		buf.put((byte)0x04);
		buf.put((byte)0x05);
		System.out.println("再写入两个数:");
		System.out.println("\t"+buf);
		buf.flip();
		byte b2 = buf.get();
		byte b3 = buf.get();
		byte b4 = buf.get();
		byte b5 = buf.get();
		System.out.println("连续读出4个:"+b2+" "+b3+" "+b4+" "+b5);
		System.out.println("\t"+buf);
	}

}
 

输出:

连续写入4个:

java.nio.HeapByteBuffer[pos=4 lim=8 cap=8]

Flip后:

java.nio.HeapByteBuffer[pos=0 lim=4 cap=8]

连续读出2个:0 1

java.nio.HeapByteBuffer[pos=2 lim=4 cap=8]

Compact后:(应用场景:上一次读没完,下一次写就开始了)

java.nio.HeapByteBuffer[pos=2 lim=8 cap=8]

再写入两个数:

java.nio.HeapByteBuffer[pos=4 lim=8 cap=8]

连续读出4个:2 3 4 5

java.nio.HeapByteBuffer[pos=4 lim=4 cap=8]




http://www.jarvana.com/jarvana/view/org/apache/mina/mina-core/2.0.0-M2/mina-core-2.0.0-M2-sources.jar!/org/apache/mina/filter/codec/CumulativeProtocolDecoder.java?format=ok

 

/*
 *  Licensed to the Apache Software Foundation (ASF) under one
 *  or more contributor license agreements.  See the NOTICE file
 *  distributed with this work for additional information
 *  regarding copyright ownership.  The ASF licenses this file
 *  to you under the Apache License, Version 2.0 (the
 *  "License"); you may not use this file except in compliance
 *  with the License.  You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing,
 *  software distributed under the License is distributed on an
 *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 *  KIND, either express or implied.  See the License for the
 *  specific language governing permissions and limitations
 *  under the License.
 *
 */
package org.apache.mina.filter.codec;

import org.apache.mina.core.buffer.IoBuffer;Class search for 'org.apache.mina.core.buffer.IoBuffer'
import org.apache.mina.core.service.TransportMetadata;Class search for 'org.apache.mina.core.service.TransportMetadata'
import org.apache.mina.core.session.AttributeKey;Class search for 'org.apache.mina.core.session.AttributeKey'
import org.apache.mina.core.session.IoSession;Class search for 'org.apache.mina.core.session.IoSession'

/**
 * A {@link ProtocolDecoder} that cumulates the content of received
 * buffers to a <em>cumulative buffer</em> to help users implement decoders.
 * <p>
 * If the received {@link IoBuffer} is only a part of a message.
 * decoders should cumulate received buffers to make a message complete or
 * to postpone decoding until more buffers arrive.
 * <p>
 * Here is an example decoder that decodes CRLF terminated lines into
 * <code>Command</code> objects:
 * <pre>
 * public class CrLfTerminatedCommandLineDecoder
 *         extends CumulativeProtocolDecoder {
 *
 *     private Command parseCommand(IoBuffer in) {
 *         // Convert the bytes in the specified buffer to a
 *         // Command object.
 *         ...
 *     }
 *
 *     protected boolean doDecode(
 *             IoSession session, IoBuffer in, ProtocolDecoderOutput out)
 *             throws Exception {
 *
 *         // Remember the initial position.
 *         int start = in.position();
 *
 *         // Now find the first CRLF in the buffer.
 *         byte previous = 0;
 *         while (in.hasRemaining()) {
 *             byte current = in.get();
 *
 *             if (previous == '\r' && current == '\n') {
 *                 // Remember the current position and limit.
 *                 int position = in.position();
 *                 int limit = in.limit();
 *                 try {
 *                     in.position(start);
 *                     in.limit(position);
 *                     // The bytes between in.position() and in.limit()
 *                     // now contain a full CRLF terminated line.
 *                     out.write(parseCommand(in.slice()));
 *                 } finally {
 *                     // Set the position to point right after the
 *                     // detected line and set the limit to the old
 *                     // one.
 *                     in.position(position);
 *                     in.limit(limit);
 *                 }
 *                 // Decoded one line; CumulativeProtocolDecoder will
 *                 // call me again until I return false. So just
 *                 // return true until there are no more lines in the
 *                 // buffer.
 *                 return true;
 *             }
 *
 *             previous = current;
 *         }
 *
 *         // Could not find CRLF in the buffer. Reset the initial
 *         // position to the one we recorded above.
 *         in.position(start);
 *
 *         return false;
 *     }
 * }
 * </pre>
 * <p>
 * Please note that this decoder simply forward the call to
 * {@link #doDecode(IoSession, IoBuffer, ProtocolDecoderOutput)} if the
 * underlying transport doesn't have a packet fragmentation.  Whether the
 * transport has fragmentation or not is determined by querying 
 * {@link TransportMetadata}.
 * 
 * @author The Apache MINA Project (dev@mina.apache.org)
 * @version $Rev: 671827 $, $Date: 2008-06-26 10:49:48 +0200 (jeu, 26 jun 2008) $
 */
public abstract class CumulativeProtocolDecoder extends ProtocolDecoderAdapter {

    private final AttributeKey BUFFER = new AttributeKey(getClass(), "buffer");

    /**
     * Creates a new instance.
     */
    protected CumulativeProtocolDecoder() {
    }

    /**
     * Cumulates content of <tt>in</tt> into internal buffer and forwards
     * decoding request to {@link #doDecode(IoSession, IoBuffer, ProtocolDecoderOutput)}.
     * <tt>doDecode()</tt> is invoked repeatedly until it returns <tt>false</tt>
     * and the cumulative buffer is compacted after decoding ends.
     *
     * @throws IllegalStateException if your <tt>doDecode()</tt> returned
     *                               <tt>true</tt> not consuming the cumulative buffer.
     */
    public void decode(IoSession session, IoBuffer in,
            ProtocolDecoderOutput out) throws Exception {
        if (!session.getTransportMetadata().hasFragmentation()) {
            doDecode(session, in, out);
            return;
        }

        boolean usingSessionBuffer = true;
        IoBuffer buf = (IoBuffer) session.getAttribute(BUFFER);
        // If we have a session buffer, append data to that; otherwise
        // use the buffer read from the network directly.
        if (buf != null) {
            boolean appended = false;
            // Make sure that the buffer is auto-expanded.
            if (buf.isAutoExpand()) {
                try {
                    buf.put(in);
                    appended = true;
                } catch (IllegalStateException e) {
                    // A user called derivation method (e.g. slice()),
                    // which disables auto-expansion of the parent buffer.
                } catch (IndexOutOfBoundsException e) {
                    // A user disabled auto-expansion.
                }
            }

            if (appended) {
                buf.flip();
            } else {
                // Reallocate the buffer if append operation failed due to
                // derivation or disabled auto-expansion.
                buf.flip();
                IoBuffer newBuf = IoBuffer.allocate(
                        buf.remaining() + in.remaining()).setAutoExpand(true);
                newBuf.order(buf.order());
                newBuf.put(buf);
                newBuf.put(in);
                newBuf.flip();
                buf = newBuf;
                
                // Update the session attribute.
                session.setAttribute(BUFFER, buf);
            }
        } else {
            buf = in;
            usingSessionBuffer = false;
        }

        for (;;) {
            int oldPos = buf.position();
            boolean decoded = doDecode(session, buf, out);
            if (decoded) {
                if (buf.position() == oldPos) {
                    throw new IllegalStateException(
                            "doDecode() can't return true when buffer is not consumed.");
                }

                if (!buf.hasRemaining()) {
                    break;
                }
            } else {
                break;
            }
        }

        // if there is any data left that cannot be decoded, we store
        // it in a buffer in the session and next time this decoder is
        // invoked the session buffer gets appended to
        if (buf.hasRemaining()) {
            if (usingSessionBuffer) {
                buf.compact();
            } else {
                storeRemainingInSession(buf, session);
            }
        } else {
            if (usingSessionBuffer) {
                removeSessionBuffer(session);
            }
        }
    }

    /**
     * Implement this method to consume the specified cumulative buffer and
     * decode its content into message(s).
     *
     * @param in the cumulative buffer
     * @return <tt>true</tt> if and only if there's more to decode in the buffer
     *         and you want to have <tt>doDecode</tt> method invoked again.
     *         Return <tt>false</tt> if remaining data is not enough to decode,
     *         then this method will be invoked again when more data is cumulated.
     * @throws Exception if cannot decode <tt>in</tt>.
     */
    protected abstract boolean doDecode(IoSession session, IoBuffer in,
            ProtocolDecoderOutput out) throws Exception;

    /**
     * Releases the cumulative buffer used by the specified <tt>session</tt>.
     * Please don't forget to call <tt>super.dispose( session )</tt> when
     * you override this method.
     */
    @Override
    public void dispose(IoSession session) throws Exception {
        removeSessionBuffer(session);
    }

    private void removeSessionBuffer(IoSession session) {
        session.removeAttribute(BUFFER);
    }

    private void storeRemainingInSession(IoBuffer buf, IoSession session) {
        final IoBuffer remainingBuf = IoBuffer.allocate(buf.capacity()).setAutoExpand(true);
        
        remainingBuf.order(buf.order());
        remainingBuf.put(buf);
        
        session.setAttribute(BUFFER, remainingBuf);
    }
}
 

 

分享到:
评论

相关推荐

    MINA使用札记(CumulativeProtocolDecoder使用)

    在MINA框架中,CumulativeProtocolDecoder是一个关键的解码器组件,它在处理网络数据流时扮演着重要角色。本文将深入探讨CumulativeProtocolDecoder的使用及其背后的原理。 CumulativeProtocolDecoder的设计目标是...

    HPsocket 封包与mina对接

    HPsocket是一个高性能、跨平台的TCP/UDP/串口通信中间件库,它提供了丰富的API接口和灵活的事件驱动模型,使得用户可以方便地开发自己的网络应用程序。本文将重点介绍如何使用HPsocket的`TcpPackServer`类来实现封包...

    2024年机器人大作业代码

    2024年机器人大作业代码

    学生信息管理系统,idea-mysql小项目,记录一下

    这是mysql文件直接导入就行了,可以查一下相关指令例如:mysql -u root -p mydb_copy < mydb.sql就好了,这里就不多赘述了

    搜索关键字飞入飞出效果.zip

    Android 毕业设计,Android 毕业设计,小Android 程设计,含有代码注释,新手也可看懂。毕业设计、期末大作业、课程设计、高分必看,下载下来,简单部署,就可以使用。 包含:项目源码、数据库脚本、软件工具等,该项目可以作为毕设、课程设计使用,前后端代码都在里面。 该系统功能完善、界面美观、操作简单、功能齐全、管理便捷,具有很高的实际应用价值。

    基于ssm的团员管理系统源代码(完整前后端+mysql+说明文档+LW).zip

    管理员 管理员信息管理 学院管理 辅导员管理 学生信息管理 公告信息 辅导员 个人资料修改 团员信息管理 优秀团员管理 团费缴纳管理 团员活动管理(主题,内容,参与人数,日期) 团员活的报名 学生 个人资料修改 入团申请管理(提交申请,申请结果查看) 团员活动查看(只能查看,不能修改,活动报名) 团员活动报名 环境说明: 开发语言:Java 框架:ssm,mybatis JDK版本:JDK1.8 数据库:mysql 5.7 数据库工具:Navicat11 开发软件:eclipse/idea Maven包:Maven3.3 服务器:tomcat7

    基于springboot图书管理系统源码+数据库+详细使用说明(高分毕设项目)

    基于springboot图书管理系统源码+数据库+详细使用说明(高分毕设项目),个人大四的毕业设计、经导师指导并认可通过的高分设计项目,评审分99分,代码完整确保可以运行,小白也可以亲自搞定,主要针对计算机相关专业的正在做毕设的学生和需要项目实战练习的学习者,也可作为课程设计、期末大作业。 基于springboot图书管理系统源码+数据库+详细使用说明(高分毕设项目)基于springboot图书管理系统源码+数据库+详细使用说明(高分毕设项目)基于springboot图书管理系统源码+数据库+详细使用说明(高分毕设项目)基于springboot图书管理系统源码+数据库+详细使用说明(高分毕设项目)基于springboot图书管理系统源码+数据库+详细使用说明(高分毕设项目)基于springboot图书管理系统源码+数据库+详细使用说明(高分毕设项目)基于springboot图书管理系统源码+数据库+详细使用说明(高分毕设项目)个人大四的毕业设计、经导师指导并认可通过的高分设计项目,评审分99分,代码完整确保可以运行,小白也可以亲自搞定,主要针对计算机相关专业的正在做毕设的学生和需要。

    Python项目-自动办公-51 Excel_案例_把文件夹整理到Excel中.zip

    Python课程设计,含有代码注释,新手也可看懂。毕业设计、期末大作业、课程设计、高分必看,下载下来,简单部署,就可以使用。 包含:项目源码、数据库脚本、软件工具等,该项目可以作为毕设、课程设计使用,前后端代码都在里面。 该系统功能完善、界面美观、操作简单、功能齐全、管理便捷,具有很高的实际应用价值。

    汽车检测33-YOLO(v5至v9)数据集合集.rar

    汽车检测33-YOLO(v5至v9)数据集合集.rar多对象-V4 2023-03-12 9:33 PM ============================= *与您的团队在计算机视觉项目上合作 *收集和组织图像 *了解和搜索非结构化图像数据 *注释,创建数据集 *导出,训练和部署计算机视觉模型 *使用主动学习随着时间的推移改善数据集 对于最先进的计算机视觉培训笔记本,您可以与此数据集一起使用 该数据集包含4278张图像。 多对象以Yolo V5 Pytorch格式注释。 将以下预处理应用于每个图像: *调整大小为640x640(拉伸) 应用以下扩展来创建每个源图像的3个版本: 将以下转换应用于每个图像的边界框: *以下90度旋转之一的同等概率:无,顺时针,逆时针方向

    Python项目-自动办公-44 excel处理实例(二维表转一维表).zip

    Python课程设计,含有代码注释,新手也可看懂。毕业设计、期末大作业、课程设计、高分必看,下载下来,简单部署,就可以使用。 包含:项目源码、数据库脚本、软件工具等,该项目可以作为毕设、课程设计使用,前后端代码都在里面。 该系统功能完善、界面美观、操作简单、功能齐全、管理便捷,具有很高的实际应用价值。

    三亚市2005-2024年近20年历史气象数据下载

    三亚市2005-2024年近20年的历史气象数据,每3小时更新一次数据,参数包含气温、气压、降水量、云层、能见度、风向、湿度等,几万条数据

    公开整理-全国高校各专业及分方向研究生录取人数大数据(更新至2022年).zip

    详细介绍及样例数据:https://blog.csdn.net/T0620514/article/details/144542157

    javaweb音乐网系统-lw.zip

    项目包含前后台完整源码。 项目都经过严格调试,确保可以运行! 具体项目介绍可查看博主文章或私聊获取 助力学习实践,提升编程技能,快来获取这份宝贵的资源吧!

    Python项目-自动办公-08 用Python设置Word文档里表格的格式.zip

    Python课程设计,含有代码注释,新手也可看懂。毕业设计、期末大作业、课程设计、高分必看,下载下来,简单部署,就可以使用。 包含:项目源码、数据库脚本、软件工具等,该项目可以作为毕设、课程设计使用,前后端代码都在里面。 该系统功能完善、界面美观、操作简单、功能齐全、管理便捷,具有很高的实际应用价值。

    STM32F103通过WIFI接收配置信息修改BC260-NBIOT模块的目标IP和端口程序代码

    1、嵌入式物联网单片机项目开发实战。例程经过精心编写,简单好用。 2、代码使用KEIL 标准库开发,当前在STM32F103运行,如果是STM32F103其他型号芯片,依然适用,请自行更改KEIL芯片型号以及FLASH容量即可。 3、软件下载时,请注意keil选择项是jlink还是stlink。 4、有偿指导v:wulianjishu666; 5、如果接入其他传感器,请查看发布的其他资料。 6、单片机与模块的接线,在代码当中均有定义,请自行对照。 7、若硬件差异,请根据自身情况调整代码,程序仅供参考学习。 8、代码有注释说明,请耐心阅读。

    瓶罐瓶子罐子检测75-YOLO(v5至v9)、COCO、CreateML、Darknet数据集合集.rar

    瓶罐瓶子罐子检测75-YOLO(v5至v9)、COCO、CreateML、Darknet数据集合集.rar街7级-V2 2023-04-28 11:45 PM ============================= *与您的团队在计算机视觉项目上合作 *收集和组织图像 *了解和搜索非结构化图像数据 *注释,创建数据集 *导出,训练和部署计算机视觉模型 *使用主动学习随着时间的推移改善数据集 对于最先进的计算机视觉培训笔记本,您可以与此数据集一起使用 该数据集包括8934张图像。 街道以可可格式注释。 将以下预处理应用于每个图像: *像素数据的自动取向(带有Exif-Arientation剥离) *调整大小为640x640(拉伸) 没有应用图像增强技术。

    基于ssm的高速公路收费系统源代码(完整前后端+mysql+说明文档+LW).zip

    管理员 管理员信息管理 负责人管理 员工信息管理 公告信息管理 小型车收费标准设置(元/每公里) 大卡车收费标准设置(元/吨公里) 收费信息统计,统计小车和卡车收费,按月统计 负责人 个人资料修改 公告查看 小车收费统计(某员工某月统计) 大卡车收费统计(某员工某月统计) 员工 个人资料修改 公告查看 小型车收费登记(车牌号,车辆照片,行使公里数,收费金额,收费日期,收费员,按公里数可以自动计算费用 收费金额=收费标准*公里数) 大卡车金额设置(每吨/元)(车牌号,车辆照片,行使公里数,吨,收费金额,收费日期,收费员, 收费金额=收费标准*吨*公里数 ) 环境说明: 开发语言:Java 框架:ssm,mybatis JDK版本:JDK1.8 数据库:mysql 5.7 数据库工具:Navicat11 开发软件:eclipse/idea Maven包:Maven3.3 服务器:tomcat7

    【图像加密解密】基于matlab Logistic映射和线性反馈移位寄存器组合的图像加密解密【含Matlab源码 9866期】复现.zip

    Matlab领域上传的视频均有对应的完整代码,皆可运行,亲测可用,适合小白; 1、代码压缩包内容 主函数:main.m; 调用函数:其他m文件;无需运行 运行结果效果图; 2、代码运行版本 Matlab 2019b;若运行有误,根据提示修改;若不会,私信博主; 3、运行操作步骤 步骤一:将所有文件放到Matlab的当前文件夹中; 步骤二:双击打开main.m文件; 步骤三:点击运行,等程序运行完得到结果; 4、仿真咨询 如需其他服务,可私信博主; 4.1 博客或资源的完整代码提供 4.2 期刊或参考文献复现 4.3 Matlab程序定制 4.4 科研合作

    Python项目-实例-08 抖音表白.zip

    Python课程设计,含有代码注释,新手也可看懂。毕业设计、期末大作业、课程设计、高分必看,下载下来,简单部署,就可以使用。 包含:项目源码、数据库脚本、软件工具等,该项目可以作为毕设、课程设计使用,前后端代码都在里面。 该系统功能完善、界面美观、操作简单、功能齐全、管理便捷,具有很高的实际应用价值。

    桌球检测10-YOLO(v5至v9)、Darknet、Paligemma、TFRecord、VOC数据集合集.rar

    桌球检测10-YOLO(v5至v9)、Darknet、Paligemma、TFRecord、VOC数据集合集.rar大理石-V3版本 ============================= *与您的团队在计算机视觉项目上合作 *收集和组织图像 *了解和搜索非结构化图像数据 *注释,创建数据集 *导出,训练和部署计算机视觉模型 *使用主动学习随着时间的推移改善数据集 对于最先进的计算机视觉培训笔记本,您可以与此数据集一起使用 该数据集包括105张图像。 大理石以Yolo V3 Darknet格式注释。 将以下预处理应用于每个图像: 没有应用图像增强技术。

Global site tag (gtag.js) - Google Analytics