mina源码分析---3

原创 2015年11月18日 22:22:42

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。

MINA框架源码分析(二)

上一篇我们通过实例学习了MINA框架的用法,发现用起来还是挺方便的,就那么几步就可以了,本着学东西必知其原理的观念,决定看看MINA的源码实现,好了,我们开始吧!         MINA源码对于客户...
  • hzw19920329
  • hzw19920329
  • 2016年08月10日 17:29
  • 3620

NIO框架之MINA源码解析(二):mina核心引擎

MINA的底层还是利用了jdk提供了nio功能,mina只是对nio进行封装,包括MINA用的线程池都是jdk直接提供的。MINA的server端主要有accept、processor、session...
  • MINEZHANGHAO
  • MINEZHANGHAO
  • 2014年09月03日 08:42
  • 5235

(二)Mina源码解析之IoService

在mina中,IoService提供基础的I/O服务、管理IoSession,它是Mina框架中最重要的一部分,大部分基础的I/O操作都是在IoService的实现类中被处理的 IoService...
  • u010031673
  • u010031673
  • 2016年04月05日 23:12
  • 2778

mina3源码分析,启动过程分析(一)

上图为服务端TCPServer类的继承关系,主要实现了IoServer和IoService两个接口,IoServer定义了bind、unbind等绑定地址的操作,IoService主要定义了Filte...
  • kangjiabang
  • kangjiabang
  • 2017年04月22日 13:31
  • 161

Mina-2.0.7源码学习 (3) ------ IoBuffer

Mina中的 IoBuffer 主要是对 Java NIO 中 ByteBuffer 的封装,
  • lgpjxjjxmumail
  • lgpjxjjxmumail
  • 2014年09月30日 15:10
  • 843

Mina2源码分析

  • 2013年05月17日 10:23
  • 558KB
  • 下载

MINA源码分析,内涵类的讲解

  • 2013年11月05日 16:02
  • 6.43MB
  • 下载

MINA源码分析---协议编码解码器工厂ProtocolCodecFactory接口

1、具体的解码器,编码器需要自己根据协议实现 2、实现协议编码解码器工厂ProtocolCodecFactory接口,在里面主要的工作就是创建解码器,编码器实例,并且返回实例 下面贴出三个接口的源...
  • cao478208248
  • cao478208248
  • 2014年12月07日 16:52
  • 1902

MINA源码分析---协议编码解码过滤器ProtocolCodecFilter

协议数据  1、对输出的数据进行编码,把消息对象转换成二进制字节流  2、对收到的数据进行解码    过滤器ProtocolCodecFilter,对应的两个最重要的方法分别是 1、先对数据进...
  • cao478208248
  • cao478208248
  • 2014年12月07日 16:40
  • 3030

mina源码分析六(转)

上文的内容还有一些没有结尾,这篇补上。在ExpiringMap类中,使用了一个私有内部类ExpiringObject来表示待检查超时的对象,它包括三个域,键,值,上次访问时间,以及用于上次访问时间这个...
  • linyu19872008
  • linyu19872008
  • 2014年02月17日 15:23
  • 513
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:mina源码分析---3
举报原因:
原因补充:

(最多只允许输入30个字)