`
Donald_Draper
  • 浏览: 984322 次
社区版块
存档分类
最新评论

Mina 累计协议解码器

    博客分类:
  • Mina
阅读更多
MINA 编解码器实例:http://donald-draper.iteye.com/blog/2375317
Mina Socket与报文过滤链:http://donald-draper.iteye.com/blog/2376440
Mina 协议编解码过滤器一(协议编解码工厂、协议编码器):
http://donald-draper.iteye.com/blog/2376663
Mina 协议编解码过滤器二(协议解码器):
http://donald-draper.iteye.com/blog/2376679
Mina 队列Queue:http://donald-draper.iteye.com/blog/2376712
Mina 协议编解码过滤器三(会话write与消息接收过滤):
http://donald-draper.iteye.com/blog/2376818
    前面我们看了一下协议编解码器,在编解码器实例这篇文章中,用的编码器不是ProtocolDecoderAdapter而是CumulativeProtocolDecoder,今天我们就来看一下可累积性协议解码器:
/**
 * A {@link ProtocolDecoder} that cumulates the content of received
 * buffers to a [i]cumulative buffer[/i] to help users implement decoders.
 * <p>CumulativeProtocolDecoder累计接收的数据到一个累计性的buffer中,以帮助使用解码数据。
 * If the received {@link ByteBuffer} 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>如果接收的数据只是消息的一部分,解码器应该累计接收的buffer,直到消息传输完成,
 或者退出解码,直到更多的buffer到达。
 * Here is an example decoder that decodes CRLF terminated lines into 
 * <code>Command</code> objects:
 * <pre>这里是一个使用CRLF为行结束符的解码器
 * public class CRLFTerminatedCommandLineDecoder 
 *         extends CumulativeProtocolDecoder {
 * 
 *     private Command parseCommand(ByteBuffer in) {
 *         // Convert the bytes in the specified buffer to a 
 *         // Command object.
 *         ...
 *     }
 * 
 *     protected boolean doDecode(IoSession session, ByteBuffer 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.
                   //记录当前位置和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.解码后恢复position,limit位置
 *                     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.解码一行数据;累计协议解码再次调用doDecode,直到doDecode返回false;
                   //则返回true,直到在buffer中,不再有一行数据,
 *                 return true;
 *             }
 *            
 *             previous = current;
 *         }
 *         如果在buffer中,没有发现换行符,则重置position位置为start
 *         // Could not find CRLF in the buffer. Reset the initial 
 *         // position to the one we recorded above.
 *         in.position(start);
 *        
 *         return false;
 *     }
 * }
 * </pre>
 * 
 * @author The Apache Directory Project (mina-dev@directory.apache.org)
 * @version $Rev$, $Date$
 */
public abstract class CumulativeProtocolDecoder extends ProtocolDecoderAdapter {

    private static final String BUFFER = CumulativeProtocolDecoder.class
            .getName()
            + ".Buffer";

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

    /**
     * Cumulates content of <tt>in</tt> into internal buffer and forwards
     * decoding request to {@link #doDecode(IoSession, ByteBuffer, ProtocolDecoderOutput)}.
     * <tt>doDecode()</tt> is invoked repeatedly until it returns <tt>false</tt>
     * and the cumulative buffer is compacted after decoding ends.
     * 累计数据放在内部buffer in中,转发解码请求到#doDecode方法,在#doDecode方法返回false之前,
     重复调用#doDecode方法解码内部in缓存数据,在每次解码结束,如果buffer中还有没解码完的数据,则
     压缩可累计buffer。
     * @throws IllegalStateException if your <tt>doDecode()</tt> returned
     *                               <tt>true</tt> not consuming the cumulative buffer.
     */
    public void decode(IoSession session, ByteBuffer in,
            ProtocolDecoderOutput out) throws Exception {
        boolean usingSessionBuffer = true;//是否开启会话缓存buffer
        ByteBuffer buf = (ByteBuffer) session.getAttribute(BUFFER);//从会话获取属性BUFFER对应的buffer
        // If we have a session buffer, append data to that; otherwise
        // use the buffer read from the network directly.
        if (buf != null) {
	    //如果会话缓存buffer不为null,则将当前in(ByteBuffer)的内容放到会话缓存buffer中
            buf.put(in);
            buf.flip();//读写模式切换
        } else { 
	    //否则直接使用当前in(ByteBuffer),将是否开启会话缓存buffer,置为否。
            buf = in;
            usingSessionBuffer = false;
        }

        for (;;) {
            int oldPos = buf.position();
	    //调用doDecode解码buffer
            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()) {
		    //如果buffer中还有数据没解码,则跳出当前循环
                    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
	//如果buffer中的数据没有解码完,则存储在会话中,以便下次解码器,将遗留的数据与
	//接收的数据一起解码
        if (buf.hasRemaining()) {
            if (usingSessionBuffer)
	        //使用缓存,则压缩buffer,将为解码的数据移到buffer的头部
                buf.compact();
            else
	        //否则存储在会话中
                storeRemainingInSession(buf, session);
        } else {
	    //如果buffer中没有数据,且开启会话缓存buffer,则从会话中移除属性BUFFER,
	    //并释放对应的buffer空间
            if (usingSessionBuffer)
                removeSessionBuffer(session);
        }
    }

    /**
     * Implement this method to consume the specified cumulative buffer and
     * decode its content into message(s). 
     *  实现此方法,用于消费累积性buffer中的数据,解码数据为上层消息对象。
     * @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, ByteBuffer 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.
     释放会话的可累计性缓存buffer,当重写此方法,不要忘了调用super.dispose( session )。
     */
    public void dispose(IoSession session) throws Exception {
        removeSessionBuffer(session);
    }
    //从会话中移除属性BUFFER,并释放对应的buffer空间
    private void removeSessionBuffer(IoSession session) {
        ByteBuffer buf = (ByteBuffer) session.removeAttribute(BUFFER);
        if (buf != null) {
            buf.release();
        }
    }
   //将buffer存储在会话属性BUFFER中
    private void storeRemainingInSession(ByteBuffer buf, IoSession session) {
        ByteBuffer remainingBuf = ByteBuffer.allocate(buf.capacity());
        remainingBuf.setAutoExpand(true);
        remainingBuf.order(buf.order());
        remainingBuf.put(buf);
        session.setAttribute(BUFFER, remainingBuf);
    }
}

总结:
累积性协议解码器decode方法,首先从会话获取属性BUFFER对应的buffer,如果会话缓存buffer不为null,则将当前in(ByteBuffer)的内容放到会话缓存buffer中;//否直接使用当前in(ByteBuffer),将是否开启会话缓存buffer,置为否;循环尝试使用doDecode方法解码数据,直到doDecode方法返回false,如果doDecode方法返回true,则继续调用doDecode方法解码数据,如果在一次解码数据返回true,但buffer中还有数据,则根据是否开启会话缓存buffer决定将buffer数据进行压缩还是存储在会话中;如果在一次解码数据返回true,但buffer中没有数据,则从会话中移除属性BUFFER,并释放对应的buffer空间。doDecode方法放抽象方法待类型实现。CumulativeProtocolDecoder实现可累性方法主要是通过将buffer存储在会话中,以实现接收数据的可累计性。
0
1
分享到:
评论

相关推荐

    mina自定义编解码器详解

    **mina自定义编解码器详解** mina是一个Java开发的网络通信框架,广泛应用于TCP和UDP协议的服务器和客户端开发。在mina框架中,编解码器(Codec)扮演着至关重要的角色,它负责将应用层的数据转换为网络传输的字节...

    MINA 协议解码过滤器

    MINA(Java Multicast Network Application Framework)是Apache软件基金会开发的一个网络应用...同时,结合提供的博客链接(虽然在这里没有具体内容),你还可以找到更多关于MINA协议解码过滤器使用的示例和实践技巧。

    mina自定义编码解码器

    本文将深入探讨如何在Mina中自定义编码解码器,这对于实现特定的网络通信协议至关重要。 首先,了解Mina的编码解码器架构是必要的。Mina使用了Chain of Responsibility设计模式,通过Filter链来处理进来的数据。...

    mina编解码器Demo

    《mina编解码器Demo详解》 mina是一个高性能、异步事件驱动的网络通信框架,主要应用于Java平台,常用于构建TCP和UDP服务。在本文中,我们将深入探讨MINA框架中的编解码器(Codec)概念,并通过提供的`mina_server`...

    Mina自定义协议简单实现

    - **编码与解码**:在Mina中,我们需要实现`org.apache.mina.core.session.IoEventType`事件的编码器和解码器,将自定义的数据结构转换成字节流在网络中传输,接收端再将字节流转回原始数据结构。 2. **创建Mina...

    mina 多路分离解码

    在mina中,我们可以自定义解码器来处理特定的协议或数据格式。例如,如果我们的应用使用了某种特定的二进制协议,我们可以创建一个解码器来解析这种协议的数据包,并将其转换为对应的Java对象。 多路分离解码的工作...

    mina编解码示例

    mina编解码示例是基于Apache Mina框架的一个实践项目,主要展示了如何在Mina中进行数据的编码和解码操作。Apache Mina是一个高度可扩展的网络通信框架,广泛应用于开发高性能、高并发的网络应用程序,如TCP/IP和UDP...

    Mina自定义协议通信的示例

    在自定义协议通信中,我们需要关注两个关键组件:自定义协议和自定义编解码器。协议定义了数据如何在网络间传输,包括数据包的结构、报头、正文以及错误处理机制。自定义编解码器则负责将这些协议规则转化为实际的...

    mina仿qq聊天功能,自定义协议,协议的编码和解码详解,发送xml对象json,mina开发大全,详细api,mina心跳

    mina仿qq聊天功能,自定义协议,协议的编码和...mina聊天 mina解码编码 mina协议开发 mina仿qq mina消息xml mina开发的在线聊天工具,mina仿qq功能,mina自定义协议,可以仿http请求,mina心跳等技术大全,mina功能大揭密

    mina通信协议文档及实例

    mina通信协议文档及实例,内含说明文档及实例,长短连接

    springboot整合mina

    下面我们将详细讨论如何在SpringBoot项目中整合Mina,并自定义解码器。 首先,我们需要在SpringBoot项目中添加Mina的相关依赖。这通常通过在`pom.xml`或`build.gradle`文件中引入Mina的依赖项来完成。对于Maven用户...

    mina HTTP协议实例

    4. **编码与解码**:MINA提供了ByteToMessageDecoder和MessageToByteEncoder接口,用于数据的解码和编码。在HTTP协议中,我们需要实现这两个接口来处理HTTP报文的二进制和文本转换。 5. **源码分析**:阅读MINA的...

    mina解码器

    在这个场景中,"mina解码器"是指使用MINA框架来实现自定义的编码和解码逻辑,以处理网络数据的收发。 解码器(Decoder)和编码器(Encoder)是MINA框架中用于处理数据传输的核心组件。它们分别负责将接收到的原始...

    mina 协议 解包 粘包

    mina 协议 解包 粘包

    MINA 心跳协议Demo

    MINA中的心跳协议可能涉及到监听器(Listener)、定时任务以及特定的事件处理机制。 MINA的核心是基于Non-blocking I/O (NIO)模型,它允许服务器处理大量并发连接,而无需为每个连接创建新的线程。NIO通过选择器...

    给予mina 协议进行大数据传输

    标题中的“给予mina协议进行大数据传输”指的是一种基于Java的网络通信框架——Apache MINA(Model-View-Controller for Network Applications)。MINA是Apache软件基金会的一个项目,它提供了一个高度可扩展和高...

    apache mina 框架实例

    以下是对Mina框架实例、自定义协议包、编码器和解码器的详细解释: **Apache Mina框架实例:** Apache Mina框架的核心思想是基于事件驱动和非阻塞I/O,这使得它在处理大量并发连接时表现出色。在Mina中,开发者可以...

    Mina断包,粘包处理(完整实例,有客户端,服务端)

    在Mina中,解决这个问题的关键在于定义正确的协议编码器和解码器。例如,你可以使用FixedLengthFrameDecoder或LineBasedFrameDecoder来确保每个接收到的数据块都能正确地组合成原始消息。 2. **粘包**: 相反,...

    java-mina通信框架详解.docx

    Apache Mina是一个强大的网络通信框架,专为基于TCP/IP和UDP/IP协议栈的应用设计。它提供了JAVA对象的序列化和虚拟机内部通信的功能,使得开发者能够迅速构建高性能、高可扩展性的网络应用。Mina的核心特性是其事件...

    mina框架自定义解编码器

    总结,MINA框架的自定义解编码器功能为我们提供了灵活的数据处理方式,通过定制解编码器,我们可以更好地适应各种网络协议和业务需求。在实践中,我们需要充分理解协议格式,合理设计解编码流程,以实现高效且可靠的...

Global site tag (gtag.js) - Google Analytics