Mina Protocol Codec Filter Two (Protocol Decoder)

Mina protocol codec filter one (protocol codec factory, protocol encoder):
http://donald-draper.iteye.com/blog/2376663

Introduction:
    In the previous article, we saw the protocol codec filter, which It involves protocol codec factories, protocol encoders, and protocol decoders.
Due to space reasons, we only look at the protocol codec factories and protocol encoders. Let’s review first:
    The protocol codec filter ProtocolCodecFilter is associated with a protocol codec factory. ProtocolCodecFactory, the protocol codec factory provides the protocol encoder ProtocolEncoder and the decoder ProtocolDecoder; the encoder encodes the message object into binary or protocol data, and the decoder decodes the binary or protocol data into the message object. The encoder ProtocolEncoder mainly has two methods, encode and dispose; encode is used to encode the upper-layer message object as binary or protocol data. mina calls the encoder's #encode method to write the message pop from the session write request queue, and then calls the ProtocolEncoderOutput#write method to put the encoded message in the ByteBuffer; the dispose method releases the encoder resources. ProtocolEncoderAdapter is an abstract implementation of the encoder. It implements dispose by default and does nothing. For encoders that do not need to release resources, inherit ProtocolEncoderAdapter. The main job of ProtocolEncoderOutput is to encode the protocol encoder
The byte buffer is cached, and the data is sent out when waiting for the flush method to be called. SimpleProtocolEncoderOutput is a simple implementation of ProtocolEncoderOutput. There is a buffer queue bufferQueue (Queue) inside, which is used to store the write (ByteBuffer) method and the incoming byte buffer; the
mergeAll method is to merge all the buffer data of the buffer queue into one buffer; the flush method is to send All buffers in the buffer queue, the actual sending work is delegated to the doFlush method to be implemented by the subclass. ProtocolEncoderOutputImpl is the inner class of the protocol codec filter. The doFlush of ProtocolEncoderOutputImpl first wraps the session into DefaultWriteFuture, and passes the session and write request information to NextFilter.

In today's article, let's take a look at the protocol decoder:
first post the code of the protocol codec filter and the protocol codec factory ProtocolCodecFactory in order to understand
//ProtocolCodecFilter
/**
 * An {@link IoFilter} which translates binary or protocol specific data into
 * message object and vice versa using {@link ProtocolCodecFactory},
 * {@link ProtocolEncoder}, or {@link ProtocolDecoder}.
 *
 * @author The Apache Directory Project ([email protected])
 * @version $Rev$, $Date$
 */
public class ProtocolCodecFilter extends IoFilterAdapter
{
    private static final Logger LOGGER = LoggerFactory.getLogger(org/apache/mina/filter/codec/ProtocolCodecFilter);
    private static final Class EMPTY_PARAMS[] = new Class[0];
    private static final IoBuffer EMPTY_BUFFER = IoBuffer.wrap(new byte[0]);
    //Encoder property key
    private static final AttributeKey ENCODER =
         new AttributeKey(org/apache/mina/filter/codec/ProtocolCodecFilter, "encoder");
    //Encoder output attribute key
    private static final AttributeKey ENCODER_OUT =
         new AttributeKey(org/apache/mina/filter/codec/ProtocolCodecFilter, "encoderOut");
    //decoder property key
    private static final AttributeKey DECODER =
         new AttributeKey(org/apache/mina/filter/codec/ProtocolCodecFilter, "decoder");  
    //decoder output attribute key
    private static final AttributeKey DECODER_OUT =
         new AttributeKey(org/apache/mina/filter/codec/ProtocolCodecFilter, "decoderOut");
    private final ProtocolCodecFactory factory;//Protocol codec factory
}

//ProtocolCodecFactory
/**
 * Provides {@link ProtocolEncoder} and {@link ProtocolDecoder} which translates
 * binary or protocol specific data into message object and vice versa.
 * <p>Protocol codec factory ProtocolCodecFactory provides protocol encoder and decoder, decoder binary data or
 Protocol data to message object; encoder vice versa.
 * Please refer to
 * [url=../../../../../xref-examples/org/apache/mina/examples/reverser/ReverseProtocolProvider.html]<code>ReverserProtocolProvider</code>[/url]
 * example.
 *  
 * @author The Apache Directory Project ([email protected])
 * @version $Rev$, $Date$
 */
public interface ProtocolCodecFactory {
    /**
     * Returns a new (or reusable) instance of {@link ProtocolEncoder} which
     * encodes message objects into binary or protocol-specific data.
     Returns an encoder instance used to encode message objects into binary or protocol data
     */
    ProtocolEncoder getEncoder() throws Exception;
    /**
     * Returns a new (or reusable) instance of {@link ProtocolDecoder} which
     * decodes binary or protocol-specific data into message objects.
     Returns a decoder instance used to decode binary or protocol data into a message object
     */
    ProtocolDecoder getDecoder() throws Exception;
}

As can be seen from the above, the protocol codec factory ProtocolCodecFactory provides the protocol encoder ProtocolEncoder and the decoder ProtocolDecoder;
the encoder encodes the message object into binary or protocol data, and the decoder decodes the binary or protocol data into a message object.
In the previous article we looked at the protocol encoder, today we will take a look at the protocol decoder:
/**
 * Decodes binary or protocol-specific data into higher-level message objects.
 * MINA invokes {@link #decode(IoSession, ByteBuffer, ProtocolDecoderOutput)}
 * method with read data, and then the decoder implementation puts decoded
 * messages into {@link ProtocolDecoderOutput} by calling
 * {@link ProtocolDecoderOutput#write(Object)}.
 * <p>
 * Please refer to
 * [url=../../../../../xref-examples/org/apache/mina/examples/reverser/TextLineDecoder.html]<code>TextLineDecoder</code>[/url]
 * example.
 *
 * @author The Apache Directory Project ([email protected])
 * @version $Rev$, $Date$
 */
public interface ProtocolDecoder {
    /**
     * Decodes binary or protocol-specific content into higher-level message objects.
     * MINA invokes {@link #decode(IoSession, ByteBuffer, ProtocolDecoderOutput)}
     * method with read data, and then the decoder implementation puts decoded
     * messages into {@link ProtocolDecoderOutput}.
     * Decode secondary or protocol memory into upper-level message objects. When mina reads data, it calls #decode of the decoder,
     Put the decoded message into ProtocolDecoderOutput
     * @throws Exception if the read data violated protocol specification
     */
    void decode(IoSession session, ByteBuffer in, ProtocolDecoderOutput out)
            throws Exception;

    /**
     * Invoked when the specified <tt>session</tt> is closed.  This method is useful
     * when you deal with the protocol which doesn't specify the length of a message
     * such as HTTP response without <tt>content-length</tt> header. Implement this
     * method to process the remaining data that {@link #decode(IoSession, ByteBuffer, ProtocolDecoderOutput)}
     * method didn't process completely.
     * Call this method when the session is closed. Especially useful when dealing with protocols without exact length, not as Http responses with no content length.
     Implement this method, mainly for
     * @throws Exception if the read data violated protocol specification
     */
    void finishDecode(IoSession session, ProtocolDecoderOutput out)
            throws Exception;

    /**
     * Releases all resources related with this decoder.
     * Release all decoder-related resources.
     * @throws Exception if failed to dispose all resources
     */
    void dispose(IoSession session) throws Exception;
}

From the above, the decoder mainly decodes the secondary or protocol memory into the upper-level message object. When mina reads data, it calls #decode of the decoder, and puts the decoded message into ProtocolDecoderOutput; when the session is closed, it calls finishDecode to decode the data that has not been processed in the #decode method. Dispose is mainly to release all the resources related to the decoder.

Let's look at the abstract implementation of the protocol decoder ProtocolDecoderAdapter
/**
 * An abstract {@link ProtocolDecoder} implementation for those who don't need
 * {@link ProtocolDecoder#finishDecode(IoSession, ProtocolDecoderOutput)} nor
 * {@link ProtocolDecoder#dispose(IoSession)} method.
 * Protocol decoding adapters are mainly for those decoders that do not require #finishDecode and #dispose
 * @author The Apache Directory Project ([email protected])
 * @version $Rev$, $Date$
 */
public abstract class ProtocolDecoderAdapter implements ProtocolDecoder {

    /**
     * Override this method to deal with the closed connection.
     * The default implementation does nothing. The session is closed
     */
    public void finishDecode(IoSession session, ProtocolDecoderOutput out)
            throws Exception {
    }

    /**
     * Override this method to dispose all resources related with this decoder.
     * The default implementation does nothing. Release resources
     */
    public void dispose(IoSession session) throws Exception {
    }
}

ProtocolDecoderAdapter The protocol decoding adapter is mainly for those decoders that do not need #finishDecode and #dispose;
mina implements corresponding adaptations for most of the components, so that we can implement the methods or events that need attention as needed,
ignore Don't care about methods or events. For example, the IoFilter->IoFilterAdapter we looked at earlier.

Let's look at the encoding output ProtocolDecoderOutput,
/**
 * Callback for {@link ProtocolDecoder} to generate decoded messages.
 * {@link ProtocolDecoder} must call {@link #write(Object)} for each decoded
 * messages.
 *
 * @author The Apache Directory Project ([email protected])
 * @version $Rev$, $Date$
 */
public interface ProtocolDecoderOutput {
    /**
     * Callback for {@link ProtocolDecoder} to generate decoded messages.
     * {@link ProtocolDecoder} must call {@link #write(Object)} for each
     * decoded messages.
     * Used in the decoder, after decoding the message, the write method is called back.
     * @param message the decoded message
     */
    void write(Object message);

    /**
     * Flushes all messages you wrote via {@link #write(Object)} to
     * the next filter. Refresh all messages written by the write method
     */
    void flush();
}

ProtocolDecoderOutput mainly has two methods, a write method, which is used by the decoder to call back after decoding the message;
a flush method, which is used to refresh all the message objects written by the decoder to the protocol decoding output.

Let's look at the simple implementation of ProtocolDecoderOutput SimpleProtocolDecoderOutput
/**
 * A {@link ProtocolDecoderOutput} based on queue.
 *
 * @author The Apache Directory Project ([email protected])
 * @version $Rev$, $Date$
 *
 */
public class SimpleProtocolDecoderOutput implements ProtocolDecoderOutput {
    private final NextFilter nextFilter;//Subsequent filter
    private final IoSession session;//Associated session
    private final Queue messageQueue = new Queue();//Message queue
    // Build simple protocol decoding output based on session and subsequent filters
    public SimpleProtocolDecoderOutput(IoSession session, NextFilter nextFilter) {
        this.nextFilter = nextFilter;
        this.session = session;
    }
    //Write a message, push the message directly to the message queue
    public void write(Object message) {
        messageQueue.push(message);
        if (session instanceof BaseIoSession) {
            ((BaseIoSession) session).increaseReadMessages();
        }
    }
    //Pass the message in the message queue to the messageReceived method of the subsequent filter.
    public void flush() {
        while (!messageQueue.isEmpty()) {
            nextFilter.messageReceived(session, messageQueue.pop());
        }

    }
}

From the above point of view, the simple protocol decoding output SimpleProtocolDecoderOutput, associated with a session session, a subsequent filter nextFilter, and a message queue messageQueue; all messages decoded by the decoder, call back the write method of the protocol decoding output, and temporarily put the message in the message In the queue messageQueue; the flush method is mainly to pass the message in the message queue to the messageReceived method of the subsequent filter.

Let's look at some codec filters to get the protocol decoding output:
//ProtocolCodecFilter
//Get the protocol decoding output
private ProtocolDecoderOutput getDecoderOut(IoSession session,
            NextFilter nextFilter) {
	//Get a ProtocolDecoderOutput of the decoded output attribute DECODER_OUT pair from the current session
        ProtocolDecoderOutput out = (ProtocolDecoderOutput) session.getAttribute(DECODER_OUT);
        if (out == null) {
	   //If it is null, create a SimpleProtocolDecoderOutput and add it to the session
            out = new SimpleProtocolDecoderOutput(session, nextFilter);
            session.setAttribute(DECODER_OUT, out);
        }
        return out;
    }

//Get the protocol encoding output
private ProtocolEncoderOutputImpl getEncoderOut(IoSession session,
            NextFilter nextFilter, WriteRequest writeRequest) {
	//This is what we talked about in the last article
        return new ProtocolEncoderOutputImpl(session, nextFilter, writeRequest);
    }

From the above, the default protocol encoding output of the protocol codec filter ProtocolCodecFilter is ProtocolEncoderOutputImpl, and the protocol decoding output is SimpleProtocolDecoderOutput.

So far, we have read the related concepts involved in the protocol codec filter and sorted it out:
the protocol codec filter is associated with a protocol codec factory, and the protocol codec factory is used to create protocol codecs and decoders; protocol encoders Encode the upper layer message into data in secondary or specific protocol format, write it to the byte queue output by the protocol encoder, and flush the data in the byte queue (filterWrite) to the next filter. The protocol decoder decodes the received data in secondary or specific protocol format into upper-layer messages, and stores them in the message queue output by the protocol decoder. Flush passes the messages in the message queue to the messageReceived method of the subsequent filter. The default protocol encoding output of the protocol codec filter ProtocolCodecFilter is ProtocolEncoderOutputImpl, and the
protocol decoding output is SimpleProtocolDecoderOutput.
The structure is as follows:
ProtocolCodecFilter extends IoFilterAdapter
   --ProtocolCodecFactory
      --ProtocolEncoder
         --ProtocolEncoderOutput(ProtocolEncoderOutputImpl)
      --ProtocolDecoder
         --ProtocolDecoderOutput(SimpleProtocolDecoderOutput)

        
Summary:
The decoder ProtocolDecoder decodes the secondary or protocol memory into an upper-level message object. When mina reads data, it calls #decode of the decoder, and puts the decoded message into ProtocolDecoderOutput; when the session is closed, it calls finishDecode to decode the data that has not been processed in the #decode method. Dispose is mainly to release all the resources related to the decoder. For decoders that do not require #finishDecode and #dispose, we can inherit the protocol decoding adapter ProtocolDecoderAdapter. ProtocolDecoderOutput has two methods, a write method, which is used by the decoder to call back after decoding the message; a flush method, which is used to flush all the message objects written by the decoder to the protocol decoding output. Simple protocol decoding output SimpleProtocolDecoderOutput, associated with a session session, a subsequent filter nextFilter, and a message queue messageQueue; all the decoded messages of the decoder, call back the write method of the protocol decoding output, and temporarily put the message in the message queue messageQueue; flush The method is mainly to pass the message in the message queue to the messageReceived method of the subsequent filter.

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=326439874&siteId=291194637