zoukankan      html  css  js  c++  java
  • Socket网络框架 MINA

    引用:http://apps.hi.baidu.com/share/detail/31519395

    http://apps.hi.baidu.com/share/user/65276d79647265616d5f7869616f3608

    MINA是一个网络应用框架,在不牺牲性能和可扩展性的前提下用于解决如下问题:
    1: 快速开发自己的英勇。
    2:高可维护性,高可复用性:网络I/O编码,消息的编/解码,业务逻辑互相分离。
    3:相对容易的进行单元测试。

     

    3.1 IoFilters:
    IoFilter为MINA的功能扩展提供了接口。它拦截所有的IO事件进行事件的预处理和后处理 (AOP)。我们可以把它想象成
    Servlet的filters。
    IoFilter能够实现以下几种目的:
    事件日志
    性能 检测
    数据转换(e.g. SSL support),codec
    防火墙…等等

    3.2 codec: ProtocolCodecFactory
    MINA提供了方便的Protocol支持。如上说讲,codec在 IoFilters中设置。
    通过它的Encoder和Decoder,可以方便的扩展并支持各种基于Socket的网络协议,比如HTTP服务 器、FTP服务器、Telnet服务器等等。

    要实现自己的编码/解码器(codec)只需要实现interface: ProtocolCodecFactory即可.
    在MINA 1.0版本,MINA已经实现了几个常用的(codec factory):

    DemuxingProtocolCodecFactory, 
    NettyCodecFactory, 
    ObjectSerializationCodecFactory, 
    TextLineCodecFactory

    其中:
     
    TextLineCodecFactory:
    A ProtocolCodecFactory that performs encoding and decoding between a text line data and a Java 
    string object. This codec is useful especially when you work with a text-based protocols such as SMTP and IMAP.

    ObjectSerializationCodecFactory:
    A ProtocolCodecFactory that serializes and deserializes Java objects. This codec is very useful when 
    you have to prototype your application rapidly without any specific codec.

    DemuxingProtocolCodecFactory:
    A composite ProtocolCodecFactory that consists of multiple MessageEncoders and MessageDecoders. ProtocolEncoder
    and ProtocolDecoder this factory returns demultiplex incoming messages and buffers to appropriate MessageEncoders 
    and MessageDecoders.

    NettyCodecFactory:
    A MINA ProtocolCodecFactory that provides encoder and decoder for Netty2 Messages and MessageRecognizers.

    3.3 business logic: IoHandler

    MINA中,所有的业务逻辑都有实现了IoHandler的class完成
    interfaceHandles:
    all protocol events fired by MINA. There are 6 event handler methods, and they are all invoked by MINA automatically. 
    当事件发生时,将触发IoHandler中的方 法:
    sessionCreated, sessionOpened, sessionClosed, sessionIdle, exceptionCaught, messageReceived, messageSent
    MINA 1.O中,IoHandler的实现类:
    ChainedIoHandler, DemuxingIoHandler, IoHandlerAdapter, SingleSessionIoHandlerDelegate, StreamIoHandler 
    具体 细节可参考javadoc。

    3.4   MINA的高级主题:线程模式
    MINA通过它灵活的filter机制来提供多种线程模型。
    没有线程池过滤器被使用时 MINA运行在一个单线程模式。
    如果添加了一个IoThreadPoolFilter到IoAcceptor,将得到一个leader- follower模式的线程池。
    如果再添加一个ProtocolThreadPoolFilter,server将有两个线程池;
    一个 (IoThreadPoolFilter)被用于对message对象进行转换,另外一个(ProtocolThreadPoolFilter)被用于处 理业务逻辑。 
    SimpleServiceRegistry加上IoThreadPoolFilter和 ProtocolThreadPoolFilter的缺省实现即可适用于需
    要高伸缩性的应用。如果想使用自己的线程模型,请参考 SimpleServiceRegistry的源代码,并且自己

    初始化Acceptor。

    IoThreadPoolFilter threadPool = new IoThreadPoolFilter();threadPool.start();
    IoAcceptor acceptor = new SocketAcceptor();
    acceptor.getFilterChain().addLast( "threadPool", threadPool);
    ProtocolThreadPoolFilter threadPool2 = new ProtocolThreadPoolFilter();
    threadPool2.start();
    ProtocolAcceptor acceptor2 = new IoProtocolAcceptor( acceptor );
    acceptor2.getFilterChain().addLast( "threadPool", threadPool2 );
    ...
    threadPool2.stop();
    threadPool.stop();


    采用MINA进行socket开发,一般步骤如下:
    1:
    server:
    IoAcceptor acceptor = new SocketAcceptor(); //建立client接收器
    or client:
    SocketConnector connector = new SocketConnector();  //建立一个连接器
    2:server的属性配置:
    SocketAcceptorConfig cfg = new SocketAcceptorConfig();
    cfg.setReuseAddress(true);
    cfg.getFilterChain().addLast(
    "codec",
    new ProtocolCodecFilter( new ObjectSerializationCodecFactory() ) ); //对象序列化 codec factory
    cfg.getFilterChain().addLast( "logger", new LoggingFilter() );
    3:绑定 address和business logic
    server:
    acceptor.bind(
    new InetSocketAddress( SERVER_PORT ),
    new ServerSessionHandler( ), cfg ); // 绑定address和handler

    client:
    connector.connect(new InetSocketAddress( HOSTNAME, PORT ),
    new ClientSessionHandler(msg), cfg );

    下面的这个简单的example演示client和server传递object的过程:
    Message.java
    public class Message implements Serializable {

        private int type;
    private int status;
    private String msgBody;

    public Message(int type, int status, String msgBody)
     
    {
    this.type = type;
    this.status = status;
    this.msgBody = msgBody;
    }

        public String getMsgBody() {
    return msgBody;
    }

        public void setMsgBody(String msgBody) {
    this.msgBody = msgBody;
    }

        public int getStatus() {
    return status;
    }

        public void setStatus(int status) {
    this.status = status;
    }

        public int getType() {
    return type;
    }

        public void setType(int type) {
    this.type = type;
    }
    }

    Client.java
    public class Client
    {
    private static final String HOSTNAME = "localhost";
    private static final int PORT = 8080;
    private static final int CONNECT_TIMEOUT = 30; // seconds


    public static void main( String[] args ) throws Throwable
    {
    SocketConnector connector = new SocketConnector();        
    // Configure the service.
    SocketConnectorConfig cfg = new SocketConnectorConfig();
    cfg.setConnectTimeout( CONNECT_TIMEOUT );
    cfg.getFilterChain().addLast(
    "codec",
    new ProtocolCodecFilter( new ObjectSerializationCodecFactory() ) );

            cfg.getFilterChain().addLast( "logger", new LoggingFilter() );

    IoSession session;
     
    Message msg = new Message(0,1,"hello");
    connector.connect(new InetSocketAddress( HOSTNAME, PORT ),
    new ClientSessionHandler(msg), cfg );

        }
    }

    ClientSessionHandler.java
    public class ClientSessionHandler extends IoHandlerAdapter
    {
    private Object msg;

    public ClientSessionHandler(Object msg)
     
    {
    this.msg = msg;
    }


    public void sessionOpened( IoSession session )
    {
    session.write(this.msg);
    }

        public void messageReceived( IoSession session, Object message )
    {
    System.out.println("in messageReceived!");
    Message rm = (Message ) message;        
    SessionLog.debug(session, rm.getMsgBody());
    System.out.println("message is: " + rm.getMsgBody());
    session.write(rm);
    }

        public void exceptionCaught( IoSession session, Throwable cause )
    {
    session.close();
    }
    }

    Server.java
    public class Server
    {
    private static final int SERVER_PORT = 8080;

        public static void main( String[] args ) throws Throwable
    {
    IoAcceptor acceptor = new SocketAcceptor();

    // Prepare the service configuration.
     
    SocketAcceptorConfig cfg = new SocketAcceptorConfig();
    cfg.setReuseAddress( true );

            cfg.getFilterChain().addLast(
    "codec",
    new ProtocolCodecFilter( new ObjectSerializationCodecFactory() ) );
    cfg.getFilterChain().addLast( "logger", new LoggingFilter() );

            acceptor.bind(
    new InetSocketAddress( SERVER_PORT ),
    new ServerSessionHandler( ), cfg );

            System.out.println( "The server Listening on port " + SERVER_PORT );
    }
    }

    ServerSessionHandler.java
    public class ServerSessionHandler extends IoHandlerAdapter
    {
    public void sessionOpened( IoSession session )
    {
    // set idle time to 60 seconds
    session.setIdleTime( IdleStatus.BOTH_IDLE, 60 );
    session.setAttribute("times",new Integer(0));
    }

        public void messageReceived( IoSession session, Object message )
    {
    System.out.println("in messageReceived");
    int times = ((Integer)(session.getAttribute("times"))).intValue();
    System.out.println("tiems = " + times);
    // communicate 30 times,then close the session.
    if (times < 30)
    {
    times++;
    session.setAttribute("times", new Integer(times));           
    Message msg;
    msg = (Message) message;
    msg.setMsgBody("in server side: " + msg.getMsgBody()); 
    System.out.println("begin send msg: " + msg.getMsgBody());
    session.write(msg);
    }
    else
    {
    session.close();
    }
    }

        public void sessionIdle( IoSession session, IdleStatus status )
    {
    SessionLog.info( session, "Disconnecting the idle." );
    // disconnect an idle client
    session.close();
    }

        public void exceptionCaught( IoSession session, Throwable cause )
    {
    // close the connection on exceptional situation
    session.close();
    }
    }
    MINA自己附带的Demo已经很好的说明了它的运用。
    值得一提的是它 的SumUp:客户端发送几个数字,服务端求和后并返回结果。这个简单的程序演示了如何自己实现CODEC。

    补充提示:
    下载并运行MINA的demo程序还颇非周折:
    运行MINA demo appli擦tion:
    1:在JDK5
    产 生错误:
    Exception in thread "main" java.lang.NoClassDefFoundError: edu/emory/mathcs/backport/java/util/concurrent/Executor
    at org.apache.mina.example.reverser.Main.main(Main.java:44)

    察看mina的 QA email:
     
    http://www.mail-archive.com/mina-dev@directory.apache.org/msg02252.html

    原来需要下载:backport-util-concurrent.jar并加入classpath
    http://dcl.mathcs.emory.edu/util/backport-util-concurrent/

    继续运行还是报错:
    Exception in thread "main" java.lang.NoClassDefFoundError: org/slf4j/LoggerFactory

    原来MINA采用了slf4j项目作为log,继续下载
    slf4j-simple.jar等,并加入classpath:
    http://www.slf4j.org/download.html

  • 相关阅读:
    Best Time to Buy and Sell Stock III
    Valid Palindrome
    Longest Substring Without Repeating Characters
    Copy List with Random Pointer
    Add Two Numbers
    Recover Binary Search Tree
    Anagrams
    ZigZag Conversion
    Merge k Sorted Lists
    Distinct Subsequences
  • 原文地址:https://www.cnblogs.com/sode/p/2346881.html
Copyright © 2011-2022 走看看