socket, nio socket 及nio socket框架MINA总结

来源:互联网 发布:软件开发英语面试 编辑:程序博客网 时间:2024/05/16 08:34
nio学习:
最近花了点时间研究了一下nio,及其开源框架MINA,现把心得总结如下:
1:传统socket:阻塞式通信
每建立一个Socket连接时,同时创建一个新线程对该Socket进行单独通信(采用阻塞的方式通信)。
这种方式具有很高的响应速度,并且控制起来也很简单,在连接数较少的时候非常有效,但是如果
对每一个连接都产生一个线程的无疑是对系统资源的一种浪费,如果连接数较多将会出现资源不足的情况
example:
server code:
Java代码 复制代码 收藏代码
  1. public class MultiUserServer extends Thread {   
  2. private Socket client;   
  3.   
  4. public MultiUserServer(Socket c) {   
  5.    this.client = c;   
  6. }   
  7.   
  8. public void run() {   
  9.    try {   
  10.     BufferedReader in = new BufferedReader(new InputStreamReader(client   
  11.       .getInputStream()));   
  12.     PrintWriter out = new PrintWriter(client.getOutputStream());   
  13.     // Mutil User but can't parallel   
  14.     while (true) {   
  15.      String str = in.readLine();   
  16.      System.out.println(str);   
  17.      SocketLog.debug("receive message: " + str);   
  18.      out.println("has receive....");   
  19.      out.flush();   
  20.      if (str.equals("end"))   
  21.       break;   
  22.     }   
  23.     client.close();   
  24.    } catch (IOException ex) {   
  25.    }    
  26. }   
  27.   
  28. public static void main(String[] args) throws IOException {   
  29.    int port = 5678;   
  30.    if (args.length > 0)   
  31.     port = Integer.parseInt(args[0]);   
  32.    ServerSocket server = new ServerSocket(port);   
  33.    SocketLog.debug("the server socket application is created!");   
  34.    while (true) {   
  35.     // transfer location change Single User or Multi User  
  36.     MultiUserServer mu = new MultiUserServer(server.accept());   
  37.     mu.start();   
  38.    }   
  39. }   
  40. }  
 
 

client code:

Java代码 复制代码 收藏代码
  1. public class Client {   
  2.   
  3. static Socket server;   
  4.   
  5. public static void main(String[] args) throws Exception {   
  6.      
  7.    //set socket proxy.   
  8.    String proxyHost = "192.168.254.212";   
  9.    String proxyPort = "1080";   
  10.    System.getProperties().put("socksProxySet","true");   
  11.    System.getProperties().put("socksProxyHost",proxyHost);   
  12.    System.getProperties().put("socksProxyPort",proxyPort);    
  13.      
  14.    String host = "132.201.69.80";   
  15.    int port = 13086;   
  16.    if (args.length > 1)   
  17.    {   
  18.     host = args[0];   
  19.     port = Integer.parseInt(args[1]);   
  20.    }   
  21.    System.out.println("connetioning:" + host + ":" + port);   
  22.    server = new Socket(host, port);   
  23.    BufferedReader in = new BufferedReader(new InputStreamReader(server   
  24.      .getInputStream()));   
  25.    PrintWriter out = new PrintWriter(server.getOutputStream());   
  26.    BufferedReader wt = new BufferedReader(new InputStreamReader(System.in));   
  27.    while (true) {   
  28.     String str = wt.readLine();   
  29.     out.println(str);   
  30.     out.flush();   
  31.     if (str.equals("end")) {   
  32.      break;   
  33.     }   
  34.     System.out.println(in.readLine());   
  35.    }   
  36.    server.close();   
  37. }   
  38. }  

 

 

2.nio:非阻塞通讯模式
2.1NIO 设计背后的基石:反应器模式,用于事件多路分离和分派的体系结构模式。
反应器模式的核心功能如下:
将事件多路分用
将事件分派到各自相应的事件处理程序

NIO 的非阻塞 I/O 机制是围绕 选择器和 通道构建的。 Channel 类表示服务器和客户机之间的
一种通信机制。Selector 类是 Channel 的多路复用器。 Selector 类将传入客户机请求多路分
用并将它们分派到各自的请求处理程序。
通道(Channel 类):表示服务器和客户机之间的一种通信机制。
选择器(Selector类):是 Channel 的多路复用器。Selector 类将传入的客户机请求多路分用并将它们
分派到各自的请求处理程序。

简单的来说:

NIO是一个基于事件的IO架构,最基本的思想就是:有事件我通知你,你再去做你的事情.
而且NIO的主线程只有一个,不像传统的模型,需要多个线程以应对客户端请求,也减轻
了JVM的工作量。
当Channel注册至Selector以后,经典的调用方法如下:

       

Java代码 复制代码 收藏代码
  1. while (somecondition) {   
  2.             int n = selector.select(TIMEOUT);   
  3.             if (n == 0)   
  4.                 continue;   
  5.             for (Iterator iter = selector.selectedKeys().iterator(); iter   
  6.                     .hasNext();) {   
  7.                 if (key.isAcceptable())   
  8.                     doAcceptable(key);   
  9.                 if (key.isConnectable())   
  10.                     doConnectable(key);   
  11.                 if (key.isValid() && key.isReadable())   
  12.                     doReadable(key);   
  13.                 if (key.isValid() && key.isWritable())   
  14.                     doWritable(key);   
  15.                 iter.remove();   
  16.             }   
  17.         }  

 

 

nio中取得事件通知,就是在selector的select事件中完成的。在selector事件时有一个线程
向操作系统询问,selector中注册的Channel&&Selecti的键值对的各种事件是否有发生,
如果有则添加到selector的selectedKeys属性Set中去,并返回本次有多少个感兴趣的事情发生。
如果发现这个值>0,表示有事件发生,马上迭代selectedKeys中的Selecti,
根据Key中的表示的事件,来做相应的处理。
实际上,这段说明表明了异步socket的核心,即异步socket不过是将多个socket的调度(或者还有他们的线程调度)
全部交给操作系统自己去完成,异步的核心Selector,不过是将这些调度收集、分发而已。
2.2 nio example:
server code:

Java代码 复制代码 收藏代码
  1. public class NonBlockingServer   
  2. {   
  3.     public Selector sel = null;   
  4.     public ServerSocketChannel server = null;   
  5.     public SocketChannel socket = null;   
  6.     public int port = 4900;   
  7.     String result = null;   
  8.   
  9.   
  10.     public NonBlockingServer()   
  11.     {   
  12.    System.out.println("Inside default ctor");   
  13.     }   
  14.        
  15. public NonBlockingServer(int port)   
  16.     {   
  17.    System.out.println("Inside the other ctor");   
  18.    this.port = port;   
  19.     }   
  20.   
  21.     public void initializeOperations() throws IOException,UnknownHostException   
  22.     {   
  23.    System.out.println("Inside initialization");   
  24.    sel = Selector.open();   
  25.    server = ServerSocketChannel.open();   
  26.    server.configureBlocking(false);   
  27.    InetAddress ia = InetAddress.getLocalHost();   
  28.    InetSocketAddress isa = new InetSocketAddress(ia,port);   
  29.    server.socket().bind(isa);   
  30.     }   
  31.        
  32. public void startServer() throws IOException   
  33.     {   
  34.    System.out.println("Inside startserver");   
  35.         initializeOperations();   
  36.    System.out.println("Abt to block on select()");   
  37.    Selecti acceptKey = server.register(sel, Selecti.OP_ACCEPT );    
  38.   
  39.    while (acceptKey.selector().select() > 0 )   
  40.    {    
  41.         
  42.     Set readyKeys = sel.selectedKeys();   
  43.     Iterator it = readyKeys.iterator();   
  44.   
  45.     while (it.hasNext()) {   
  46.      Selecti key = (Selecti)it.next();   
  47.      it.remove();   
  48.                    
  49.      if (key.isAcceptable()) {   
  50.       System.out.println("Key is Acceptable");   
  51.       ServerSocketChannel ssc = (ServerSocketChannel) key.channel();   
  52.       socket = (SocketChannel) ssc.accept();   
  53.       socket.configureBlocking(false);   
  54.       Selecti another = socket.register(sel,Selecti.OP_READ|Selecti.OP_WRITE);   
  55.      }   
  56.      if (key.isReadable()) {   
  57.       System.out.println("Key is readable");   
  58.       String ret = readMessage(key);   
  59.       if (ret.length() > 0) {   
  60.        writeMessage(socket,ret);   
  61.       }   
  62.      }   
  63.      if (key.isWritable()) {   
  64.       System.out.println("THe key is writable");   
  65.       String ret = readMessage(key);   
  66.       socket = (SocketChannel)key.channel();   
  67.       if (result.length() > 0 ) {   
  68.        writeMessage(socket,ret);   
  69.       }   
  70.      }   
  71.     }   
  72.    }   
  73.     }   
  74.   
  75.     public void writeMessage(SocketChannel socket,String ret)   
  76.     {   
  77.    System.out.println("Inside the loop");   
  78.   
  79.    if (ret.equals("quit") || ret.equals("shutdown")) {   
  80.     return;   
  81.    }   
  82.    try  
  83.    {   
  84.   
  85.     String s = "This is context from server!-----------------------------------------";   
  86.     Charset set = Charset.forName("us-ascii");   
  87.     CharsetDecoder dec = set.newDecoder();   
  88.     CharBuffer charBuf = dec.decode(ByteBuffer.wrap(s.getBytes()));   
  89.     System.out.println(charBuf.toString());   
  90.     int nBytes = socket.write(ByteBuffer.wrap((charBuf.toString()).getBytes()));   
  91.     System.out.println("nBytes = "+nBytes);   
  92.      result = null;   
  93.    }   
  94.    catch(Exception e)   
  95.    {   
  96.     e.printStackTrace();   
  97.    }   
  98.   
  99.     }   
  100.   
  101.     public String readMessage(Selecti key)   
  102.     {   
  103.    int nBytes = 0;   
  104.    socket = (SocketChannel)key.channel();   
  105.         ByteBuffer buf = ByteBuffer.allocate(1024);   
  106.    try  
  107.    {   
  108.             nBytes = socket.read(buf);   
  109.     buf.flip();   
  110.     Charset charset = Charset.forName("us-ascii");   
  111.     CharsetDecoder decoder = charset.newDecoder();   
  112.     CharBuffer charBuffer = decoder.decode(buf);   
  113.     result = charBuffer.toString();   
  114.         
  115.         }   
  116.    catch(IOException e)   
  117.    {   
  118.     e.printStackTrace();   
  119.    }   
  120.    return result;   
  121.     }   
  122.   
  123.     public static void main(String args[])   
  124.     {   
  125.     NonBlockingServer nb;   
  126.     if (args.length < 1)   
  127.     {   
  128.        nb = new NonBlockingServer();   
  129.     }   
  130.     else  
  131.     {   
  132.        int port = Integer.parseInt(args[0]);   
  133.        nb = new NonBlockingServer(port);   
  134.     }   
  135.       
  136.    try  
  137.    {   
  138.     nb.startServer();   
  139.     System.out.println("the nonBlocking server is started!");   
  140.    }   
  141.    catch (IOException e)   
  142.    {   
  143.     e.printStackTrace();   
  144.     System.exit(-1);   
  145.    }   
  146.      
  147. }   
  148. }  

 


client code:

Java代码 复制代码 收藏代码
  1. public class Client {   
  2. public SocketChannel client = null;   
  3.   
  4. public InetSocketAddress isa = null;   
  5.   
  6. public RecvThread rt = null;   
  7.   
  8. private String host;   
  9.   
  10. private int port;   
  11.   
  12. public Client(String host, int port) {   
  13.    this.host = host;   
  14.    this.port = port;   
  15. }   
  16.   
  17. public void makeConnection() {   
  18.    String proxyHost = "192.168.254.212";   
  19.    String proxyPort = "1080";   
  20.    System.getProperties().put("socksProxySet""true");   
  21.    System.getProperties().put("socksProxyHost", proxyHost);   
  22.    System.getProperties().put("socksProxyPort", proxyPort);   
  23.   
  24.    int result = 0;   
  25.    try {   
  26.     client = SocketChannel.open();   
  27.     isa = new InetSocketAddress(host, port);   
  28.     client.connect(isa);   
  29.     client.configureBlocking(false);   
  30.     receiveMessage();   
  31.    } catch (UnknownHostException e) {   
  32.     e.printStackTrace();   
  33.    } catch (IOException e) {   
  34.     e.printStackTrace();   
  35.    }   
  36.    long begin = System.currentTimeMillis();   
  37.   
  38.    sendMessage();   
  39.   
  40.    long end = System.currentTimeMillis();   
  41.    long userTime = end - begin;   
  42.    System.out.println("use tiem: " + userTime);   
  43.    try {   
  44.     interruptThread();   
  45.     client.close();   
  46.     System.exit(0);   
  47.    } catch (IOException e) {   
  48.     e.printStackTrace();   
  49.    }   
  50. }   
  51.   
  52. public int sendMessage() {   
  53.      System.out.println("Inside SendMessage");   
  54.    String msg = null;   
  55.    ByteBuffer bytebuf;   
  56.    int nBytes = 0;   
  57.    try {   
  58.     msg = "It's message from client!";   
  59.     System.out.println("msg is "+msg);   
  60.     bytebuf = ByteBuffer.wrap(msg.getBytes());   
  61.     for (int i = 0; i < 1000; i++) {   
  62.      nBytes = client.write(bytebuf);   
  63.      System.out.println(i + " finished");   
  64.     }   
  65.     interruptThread();   
  66.     try {   
  67.      Thread.sleep(5000);   
  68.     } catch (Exception e) {   
  69.      e.printStackTrace();   
  70.     }   
  71.     client.close();   
  72.     return -1;   
  73.   
  74.    } catch (IOException e) {   
  75.     e.printStackTrace();   
  76.    }   
  77.   
  78.    return nBytes;   
  79.   
  80. }   
  81.   
  82. public void receiveMessage() {   
  83.    rt = new RecvThread("Receive THread", client);   
  84.    rt.start();   
  85.   
  86. }   
  87.   
  88. public void interruptThread() {   
  89.    rt.val = false;   
  90. }   
  91.   
  92. public static void main(String args[]) {   
  93.    if (args.length < 2) {   
  94.     System.err.println("You should put 2 args: host,port");   
  95.    } else {   
  96.     String host = args[0];   
  97.     int port = Integer.parseInt(args[1]);   
  98.     Client cl = new Client(host, port);   
  99.     cl.makeConnection();   
  100.    }   
  101.    BufferedReader in = new BufferedReader(new InputStreamReader(System.in));   
  102.    String msg;   
  103.   
  104. }   
  105.   
  106. public class RecvThread extends Thread {   
  107.    public SocketChannel sc = null;   
  108.   
  109.    public boolean val = true;   
  110.   
  111.    public RecvThread(String str, SocketChannel client) {   
  112.     super(str);   
  113.     sc = client;   
  114.    }   
  115.   
  116.    public void run() {   
  117.     int nBytes = 0;   
  118.     ByteBuffer buf = ByteBuffer.allocate(2048);   
  119.     try {   
  120.      while (val) {   
  121.       while ((nBytes = nBytes = client.read(buf)) > 0) {   
  122.        buf.flip();   
  123.        Charset charset = Charset.forName("us-ascii");   
  124.        CharsetDecoder decoder = charset.newDecoder();   
  125.        CharBuffer charBuffer = decoder.decode(buf);   
  126.        String result = charBuffer.toString();   
  127.        System.out.println("the server return: " + result);   
  128.        buf.flip();   
  129.   
  130.       }   
  131.      }   
  132.   
  133.     } catch (IOException e) {   
  134.      e.printStackTrace();   
  135.   
  136.     }   
  137.   
  138.    }   
  139. }   
  140. }  

 

 

3:Socket网络框架 MINA
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

Java代码 复制代码 收藏代码
  1. public class Message implements Serializable {   
  2.   
  3.     private int type;   
  4.     private int status;   
  5.     private String msgBody;   
  6.        
  7.     public Message(int type, int status, String msgBody)   
  8.     {   
  9.         this.type = type;   
  10.         this.status = status;   
  11.         this.msgBody = msgBody;   
  12.     }   
  13.   
  14.     public String getMsgBody() {   
  15.         return msgBody;   
  16.     }   
  17.   
  18.     public void setMsgBody(String msgBody) {   
  19.         this.msgBody = msgBody;   
  20.     }   
  21.   
  22.     public int getStatus() {   
  23.         return status;   
  24.     }   
  25.   
  26.     public void setStatus(int status) {   
  27.         this.status = status;   
  28.     }   
  29.   
  30.     public int getType() {   
  31.         return type;   
  32.     }   
  33.   
  34.     public void setType(int type) {   
  35.         this.type = type;   
  36.     }   
  37. }  

 

Client.java

Java代码 复制代码 收藏代码
  1. public class Client   
  2. {   
  3.     private static final String HOSTNAME = "localhost";   
  4.     private static final int PORT = 8080;   
  5.     private static final int CONNECT_TIMEOUT = 30// seconds  
  6.   
  7.   
  8.     public static void main( String[] args ) throws Throwable   
  9.     {   
  10.         SocketConnector connector = new SocketConnector();           
  11.         // Configure the service.   
  12.         SocketConnectorConfig cfg = new SocketConnectorConfig();   
  13.         cfg.setConnectTimeout( CONNECT_TIMEOUT );   
  14.           cfg.getFilterChain().addLast(   
  15.                     "codec",   
  16.                     new ProtocolCodecFilter( new ObjectSerializationCodecFactory() ) );   
  17.   
  18.         cfg.getFilterChain().addLast( "logger"new LoggingFilter() );   
  19.            
  20.         IoSession session;   
  21.         Message msg = new Message(0,1,"hello");   
  22.         connector.connect(new InetSocketAddress( HOSTNAME, PORT ),   
  23.                         new ClientSessionHandler(msg), cfg );   
  24.   
  25.     }   
  26. }  

 


ClientSessionHandler.java

Java代码 复制代码 收藏代码
  1. public class ClientSessionHandler extends IoHandlerAdapter   
  2. {   
  3.     private Object msg;   
  4.        
  5.     public ClientSessionHandler(Object msg)   
  6.     {   
  7.         this.msg = msg;   
  8.     }   
  9.   
  10.   
  11.     public void sessionOpened( IoSession session )   
  12.     {   
  13.         session.write(this.msg);   
  14.     }   
  15.   
  16.     public void messageReceived( IoSession session, Object message )   
  17.     {   
  18.         System.out.println("in messageReceived!");   
  19.         Message rm = (Message ) message;           
  20.         SessionLog.debug(session, rm.getMsgBody());   
  21.         System.out.println("message is: " + rm.getMsgBody());   
  22.         session.write(rm);   
  23.     }   
  24.   
  25.     public void exceptionCaught( IoSession session, Throwable cause )   
  26.     {   
  27.         session.close();   
  28.     }   
  29. }  

 

 

Server.java

Java代码 复制代码 收藏代码
  1. public class Server   
  2. {   
  3.     private static final int SERVER_PORT = 8080;   
  4.   
  5.     public static void main( String[] args ) throws Throwable   
  6.     {   
  7.         IoAcceptor acceptor = new SocketAcceptor();   
  8.            
  9.         // Prepare the service configuration.  
  10.         SocketAcceptorConfig cfg = new SocketAcceptorConfig();   
  11.         cfg.setReuseAddress( true );   
  12.   
  13.         cfg.getFilterChain().addLast(   
  14.                     "codec",   
  15.                     new ProtocolCodecFilter( new ObjectSerializationCodecFactory() ) );   
  16.         cfg.getFilterChain().addLast( "logger"new LoggingFilter() );   
  17.   
  18.         acceptor.bind(   
  19.                 new InetSocketAddress( SERVER_PORT ),   
  20.                 new ServerSessionHandler( ), cfg );   
  21.   
  22.         System.out.println( "The server Listening on port " + SERVER_PORT );   
  23.     }   
  24. }  

 

 

ServerSessionHandler.java

Java代码 复制代码 收藏代码
  1. public class ServerSessionHandler extends IoHandlerAdapter   
  2. {   
  3.     public void sessionOpened( IoSession session )   
  4.     {   
  5.         // set idle time to 60 seconds   
  6.         session.setIdleTime( IdleStatus.BOTH_IDLE, 60 );   
  7.         session.setAttribute("times",new Integer(0));   
  8.     }   
  9.   
  10.     public void messageReceived( IoSession session, Object message )   
  11.     {   
  12.         System.out.println("in messageReceived");   
  13.         int times = ((Integer)(session.getAttribute("times"))).intValue();   
  14.         System.out.println("tiems = " + times);   
  15.         // communicate 30 times,then close the session.  
  16.         if (times < 30)   
  17.         {   
  18.             times++;   
  19.             session.setAttribute("times"new Integer(times));              
  20.          Message msg;   
  21.          msg = (Message) message;   
  22.          msg.setMsgBody("in server side: " + msg.getMsgBody());    
  23.          System.out.println("begin send msg: " + msg.getMsgBody());   
  24.          session.write(msg);   
  25.         }   
  26.         else  
  27.         {   
  28.             session.close();   
  29.         }   
  30.     }   
  31.   
  32.     public void sessionIdle( IoSession session, IdleStatus status )   
  33.     {   
  34.         SessionLog.info( session, "Disconnecting the idle." );   
  35.         // disconnect an idle client   
  36.         session.close();   
  37.     }   
  38.   
  39.     public void exceptionCaught( IoSession session, Throwable cause )   
  40.     {   
  41.         // close the connection on exceptional situation  
  42.         session.close();   
  43.     }   
  44. }  

 

 

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

原创粉丝点击