MINA源码分析---协议编码输出接口ProtocolEncoderOutput及其实现

来源:互联网 发布:手机人物模型软件 编辑:程序博客网 时间:2024/05/18 09:19

下面是协议编码输出接口ProtocolEncoderOutput,

所有编码后的数据需要通过接口ProtocolEncoderOutput来写到会话中

package org.apache.mina.filter.codec;import org.apache.mina.core.buffer.IoBuffer;import org.apache.mina.core.file.FileRegion;import org.apache.mina.core.future.WriteFuture;/** * Callback for {@link ProtocolEncoder} to generate encoded messages such as * {@link IoBuffer}s.  {@link ProtocolEncoder} must call {@link #write(Object)} * for each encoded message. *  */public interface ProtocolEncoderOutput {    /**     * Callback for {@link ProtocolEncoder} to generate an encoded message such     * as an {@link IoBuffer}. {@link ProtocolEncoder} must call     * {@link #write(Object)} for each encoded message.     * ProtocolEncoder中的ecode方法会对每一个编码的信息 调用 此函数     * @param encodedMessage the encoded message, typically an {@link IoBuffer}     *                       or a {@link FileRegion}.     */    void write(Object encodedMessage);    /**     * Merges all buffers you wrote via {@link #write(Object)} into     * one {@link IoBuffer} and replaces the old fragmented ones with it.     * This method is useful when you want to control the way MINA generates     * network packets.  Please note that this method only works when you     * called {@link #write(Object)} method with only {@link IoBuffer}s.     * 合并所有IoBuffer缓冲区     * @throws IllegalStateException if you wrote something else than {@link IoBuffer}     */    void mergeAll();    /**     * Flushes all buffers you wrote via {@link #write(Object)} to     * the session.把所有通过 write(Object)方法写到缓冲区的数据刷新到会话中     * This operation is asynchronous这个方法是异步的,看后面的实现writeFuture; please wait for     * the returned {@link WriteFuture} if you want to wait for     * the buffers flushed.     *     * @return <tt>null</tt> if there is nothing to flush at all.     */    WriteFuture flush();}

接口ProtocolEncoderOutput的一个抽象类实现,主要实现了合并数据方法

package org.apache.mina.filter.codec;import java.util.Queue;import java.util.concurrent.ConcurrentLinkedQueue;import org.apache.mina.core.buffer.IoBuffer;/** * A {@link ProtocolEncoderOutput} based on queue. * 基于并发队列的协议编码输出器 */public abstract class AbstractProtocolEncoderOutput implements        ProtocolEncoderOutput {    private final Queue<Object> messageQueue = new ConcurrentLinkedQueue<Object>();    private boolean buffersOnly = true;    public AbstractProtocolEncoderOutput() {        // Do nothing    }    public Queue<Object> getMessageQueue() {        return messageQueue;    }    //所有信息放到消息队列中,等待读写    public void write(Object encodedMessage) {        if (encodedMessage instanceof IoBuffer) {            IoBuffer buf = (IoBuffer) encodedMessage;            if (buf.hasRemaining()) {                messageQueue.offer(buf);            } else {                throw new IllegalArgumentException(                        "buf is empty. Forgot to call flip()?");            }        } else {            messageQueue.offer(encodedMessage);            buffersOnly = false;        }    }    //合并所有消息    public void mergeAll() {        if (!buffersOnly) {//如果不是IoBuffer,则抛出异常            throw new IllegalStateException(                    "the encoded message list contains a non-buffer.");        }                final int size = messageQueue.size();        if (size < 2) {            // no need to merge!            return;        }        // Get the size of merged BB        int sum = 0;        for (Object b : messageQueue) {            sum += ((IoBuffer) b).remaining();        }        // Allocate a new BB that will contain all fragments        IoBuffer newBuf = IoBuffer.allocate(sum);        // and merge all.        for (; ;) {            IoBuffer buf = (IoBuffer) messageQueue.poll();            if (buf == null) {                break;            }            newBuf.put(buf);        }        // Push the new buffer finally.        newBuf.flip();        messageQueue.add(newBuf);    }}


此类主要实现了flush方法

    //协议编码器输出的一个实现    private static class ProtocolEncoderOutputImpl extends            AbstractProtocolEncoderOutput {        private final IoSession session;        private final NextFilter nextFilter;        private final WriteRequest writeRequest;        public ProtocolEncoderOutputImpl(IoSession session,                NextFilter nextFilter, WriteRequest writeRequest) {            this.session = session;            this.nextFilter = nextFilter;            this.writeRequest = writeRequest;        }        public WriteFuture flush() {            Queue<Object> bufferQueue = getMessageQueue();            WriteFuture future = null;                        while (!bufferQueue.isEmpty()) {                Object encodedMessage = bufferQueue.poll();                if (encodedMessage == null) {                    break;                }                // Flush only when the buffer has remaining.                if (!(encodedMessage instanceof IoBuffer) ||                 ((IoBuffer) encodedMessage).hasRemaining())                 {                    future = new DefaultWriteFuture(session);                    nextFilter.filterWrite(session, new EncodedWriteRequest(encodedMessage,                            future, writeRequest.getDestination()));                }            }            if (future == null) {                future = DefaultWriteFuture.newNotWrittenFuture(                        session, new NothingWrittenException(writeRequest));            }            return future;        }    }



0 0