MINA学习之体系介绍

基于MINA应用程序结构图:


我们可以看出,MINA是应用程序(客户端或服务端)和底层基于TCP,UDP等通讯协议的网络层之间的粘合剂。而且各个模块之间是相互独立的,你只需要在MINA体

系基础上设计你的应用程序,而不用去处理复杂的网络层。

下图展示了MINA的内部组件以及MINA各个组件的功能。



很显然,基于MINA的应用程序被划分为3层:

1. I/O Service  -- 执行真正的I/O操作

2. I/O Filter Chain -- 过滤,转换字节流为想要的数据结构

3. I/O Handler -- 实现顶层业务逻辑 

因此,想要创建基于MINA的应用程序,须完成以下操作:

      1. 创建 I/O Service  --从已有可用的Service(*Acceptor) 或创建你定义的

      2. 创建Filter Chain  --  从已有可有的Filter中选择或者创建自定义的Filter

      3. 创建I/O Handler  -- 写业务逻辑来处理不同的消息


MINA服务端体系

上文已经介绍了基于MINA应用程序的一个整体的结构,现在我们来看看服务端的结构。主要来说,服务端侦听一个端口来接受请求,处理请求并给出响应。并且服务端也会为

每一个客户端维护一个Session,Session以后会详细介绍。


MINA服务端处理流程:

1. IOAcceptor 侦听网络上的链接和包

2. 针对每一个链接,一个新的session将会被创建,并且随后该 Ip+ 端口上的请求都会被这个session处理

3. 所有的包从Session处接受后,传送给Filter,Filters 用于修改包内容(如将字节流转换成特定的java bean,增加或删除信息等等),将字节流和java bean业务对象之

    相互转换常常会用到PacketEncoder / Decoder两个类

4. 最后,转换后的包或对象将由IOHandler来处理


Session 创建:

只要有客户端连接到MINA服务端,都会为该链接创建一个Sessiion并在Session存放一些数据。

传入的消息处理:

假设一个Session已经被创建,任何传入的消息都将会导致Selector唤醒。


MINA 客户端体系

上文已经介绍了MINA结构体系以及服务端体系,现在来介绍下MINA的客户端结构体系。客户端需要连接上服务端,并发送请求和处理应答。



MINA客户端处理流程:

1. 客户端首先创建一个IOConnector(MINA 体系中的结构,用于Socket连接),然后绑定到服务端(即连接到服务端的IP和端口)。
2. 连接建立后,将会创建一个Session并将该session绑定到连接上

3. 应用程序或客户端向session中写入数据,在经过过滤器链(Filter Chain)转换后,发送给服务端

4. session接收到从服务端发送过来的数据,经过Filter Chain过滤转换处理后,交由IOHandler去处理


Simple Tcp Server


1. 服务端 IOHandler
import java.util.Date;

import org.apache.mina.core.session.IdleStatus;
import org.apache.mina.core.service.IoHandlerAdapter;
import org.apache.mina.core.session.IoSession;

public class TimeServerHandler extends IoHandlerAdapter
{
    @Override
    public void exceptionCaught( IoSession session, Throwable cause ) throws Exception
    {
        cause.printStackTrace();
    }
    @Override
    public void messageReceived( IoSession session, Object message ) throws Exception
    {
        String str = message.toString();
        if( str.trim().equalsIgnoreCase("quit") ) {
            session.close();
            return;
        }
        Date date = new Date();
        session.write( date.toString() );
        System.out.println("Message written...");
    }
    @Override
    public void sessionIdle( IoSession session, IdleStatus status ) throws Exception
    {
        System.out.println( "IDLE " + session.getIdleCount( status ));
    }
}
2. 启动服务端
import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.charset.Charset;

import org.apache.mina.core.service.IoAcceptor;
import org.apache.mina.core.session.IdleStatus;
import org.apache.mina.filter.codec.ProtocolCodecFilter;
import org.apache.mina.filter.codec.textline.TextLineCodecFactory;
import org.apache.mina.filter.logging.LoggingFilter;
import org.apache.mina.transport.socket.nio.NioSocketAcceptor;

public class MinaTimeServer
{
    private static final int PORT = 9123;
    public static void main( String[] args ) throws IOException
    {
        IoAcceptor acceptor = new NioSocketAcceptor();
        acceptor.getFilterChain().addLast( "logger", new LoggingFilter() );
        acceptor.getFilterChain().addLast( "codec", new ProtocolCodecFilter( new TextLineCodecFactory( Charset.forName( "UTF-8" ))));
        acceptor.setHandler( new TimeServerHandler() );
        acceptor.getSessionConfig().setReadBufferSize( 2048 );
        acceptor.getSessionConfig().setIdleTime( IdleStatus.BOTH_IDLE, 10 );
        acceptor.bind( new InetSocketAddress(PORT) );
    }
}

3. 启动服务端后,可用telnet 127.0.0.1 9123 来测试。

Simple Tcp Clinent:


1. IOHandler 省略

2. 客户端连接到服务端
public static void main(String[] args) throws Throwable {
    NioSocketConnector connector = new NioSocketConnector();
    connector.setConnectTimeoutMillis(CONNECT_TIMEOUT);

    if (USE_CUSTOM_CODEC) {
    connector.getFilterChain().addLast("codec",
        new ProtocolCodecFilter(new SumUpProtocolCodecFactory(false)));
    } else {
        connector.getFilterChain().addLast("codec",
            new ProtocolCodecFilter(new ObjectSerializationCodecFactory()));
    }

    connector.getFilterChain().addLast("logger", new LoggingFilter());
    connector.setHandler(new ClientSessionHandler(values));
    IoSession session;

    for (;;) {
        try {
            ConnectFuture future = connector.connect(new InetSocketAddress(HOSTNAME, PORT));
            future.awaitUninterruptibly();
            session = future.getSession();
            break;
        } catch (RuntimeIoException e) {
            System.err.println("Failed to connect.");
            e.printStackTrace();
            Thread.sleep(5000);
        }
    }

    // wait until the summation is done
    session.getCloseFuture().awaitUninterruptibly();
    connector.dispose();
}



至此,简单介绍了MINA的整体结构,服务端结构,客户端结构及各自的处理流程,下篇将会介绍IOService层。
posted @ 2014-04-24 08:57  marco_tan  阅读(284)  评论(0编辑  收藏  举报