关闭

mina源码分析---3

317人阅读 评论(0) 收藏 举报
分类:

process源码分析

上一章分析了processHandles函数,本章开始将要分析processHandles中的process函数,该函数是处理客户端请求的核心函数。process定义在AbstractPollingIoProcessor中,

    private void process() throws Exception {
        for (Iterator<S> i = selectedSessions(); i.hasNext();) {
            S session = i.next();
            process(session);
            i.remove();
        }
    }

这里就是依次取出Nio中发生相应时间的NioSocketSession,并进一步执行process函数,

    private void process(S session) {

        if (isReadable(session) && !session.isReadSuspended()) {
            read(session);
        }

        if (isWritable(session) && !session.isWriteSuspended()) {
            if (session.setScheduledForFlush(true)) {
                flushingSessions.add(session);
            }
        }
    }

isReadable和isWritable用于判断Nio中产生的key是哪种时间,isReadSuspended和isWriteSuspended则就是两个bool变量,用于控制读写。下面假设判定通过,如果是写事件,则很简单,将该Session添加进flushingSessions后,后续便能写入写缓存中(查看上一章的flush函数)。这里主要分析读事件,

read

    private void read(S session) {
        IoSessionConfig config = session.getConfig();
        int bufferSize = config.getReadBufferSize();
        IoBuffer buf = IoBuffer.allocate(bufferSize);

        final boolean hasFragmentation = session.getTransportMetadata().hasFragmentation();

        try {
            int readBytes = 0;
            int ret;

            try {
                if (hasFragmentation) {

                    while ((ret = read(session, buf)) > 0) {
                        readBytes += ret;

                        if (!buf.hasRemaining()) {
                            break;
                        }
                    }
                } else {
                    ret = read(session, buf);

                    if (ret > 0) {
                        readBytes = ret;
                    }
                }
            } finally {
                buf.flip();
            }

            if (readBytes > 0) {
                IoFilterChain filterChain = session.getFilterChain();
                filterChain.fireMessageReceived(buf);
                buf = null;

                if (hasFragmentation) {
                    if (readBytes << 1 < config.getReadBufferSize()) {
                        session.decreaseReadBufferSize();
                    } else if (readBytes == config.getReadBufferSize()) {
                        session.increaseReadBufferSize();
                    }
                }
            }
        } catch (Exception e) {

        }
    }

该函数主要做了两件事情,一是调用read通过Nio的Channel将数据读进缓存中,二是调用IoFilterChain的fireMessageReceived函数。先看read函数,具体的读函数read定义在NioProcessor中,

    protected int read(NioSession session, IoBuffer buf) throws Exception {
        ByteChannel channel = session.getChannel();

        return channel.read(buf.buf());
    }

这里就是简单的调用Nio的Channel将数据读入缓存,具体的过程可以参考Nio的源码。
回到前面的read函数中,如果读入数据成功,就从NioSocketSession中获取IoFilterChain并调用其fireMessageReceived函数,getFilterChain返回的IoFilterChain是DefaultIoFilterChain。
在使用mina框架时,开发者可以定义自己的过滤器添加进mina中,mina默认实现了两个过滤器,看DefaultIoFilterChain的构造函数,

    public DefaultIoFilterChain(AbstractIoSession session) {
        if (session == null) {
            throw new IllegalArgumentException("session");
        }

        this.session = session;
        head = new EntryImpl(null, null, "head", new HeadFilter());
        tail = new EntryImpl(head, null, "tail", new TailFilter());
        head.nextEntry = tail;
    }

因此,mina框架默认实现了HeadFilter和TailFilter。

fireMessageReceived

fireMessageReceived定义在DefaultIoFilterChain中,

    public void fireMessageReceived(Object message) {
        if (message instanceof IoBuffer) {
            session.increaseReadBytes(((IoBuffer) message).remaining(), System.currentTimeMillis());
        }

        callNextMessageReceived(head, session, message);
    }

这里就是简单调用callNextMessageReceived进行进一步的处理,传入的参数head是过滤器链表的指针头,session是NioSocketSession,message就是读入的数据。

    private void callNextMessageReceived(Entry entry, IoSession session, Object message) {
        try {
            IoFilter filter = entry.getFilter();
            NextFilter nextFilter = entry.getNextFilter();
            filter.messageReceived(nextFilter, session, message);
        } catch (Exception e) {

        } 
    }

这里就是从entry中取出过滤器filter,调用其messageReceived函数。默认必然会取出2个filter,一个是HeadFilter,另一个是TailFilter。其中,HeadFilter在处理消息时什么都不会做,TailFilter的messageReceived如下

        public void messageReceived(NextFilter nextFilter, IoSession session, Object message) throws Exception {
            AbstractIoSession s = (AbstractIoSession) session;

            try {
                session.getHandler().messageReceived(s, message);
            } finally {
                if (s.getConfig().isUseReadOperation()) {
                    s.offerReadFuture(message);
                }
            }
        }

因此,TailFilter会调用其中的注册的handler对消息进行处理,getHandler返回的是一个IoHandler。

0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:77737次
    • 积分:1610
    • 等级:
    • 排名:千里之外
    • 原创:75篇
    • 转载:0篇
    • 译文:0篇
    • 评论:3条
    最新评论