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

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.161.88.22";  
  9.   String proxyPort = "2080";  
  10.   System.getProperties().put("socksProxySet","true");  
  11.   System.getProperties().put("socksProxyHost",proxyHost);  
  12.   System.getProperties().put("socksProxyPort",proxyPort);   
  13.     
  14.   String host = "192.20.9.18";  
  15.   int port = 1086;  
  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&&SelectionKey的键值对的各种事件是否有发生, 
如果有则添加到selector的selectedKeys属性Set中去,并返回本次有多少个感兴趣的事情发生。 
如果发现这个值>0,表示有事件发生,马上迭代selectedKeys中的SelectionKey, 
根据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.   SelectionKey acceptKey = server.register(sel, SelectionKey.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.     SelectionKey key = (SelectionKey)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.      SelectionKey another = socket.register(sel,SelectionKey.OP_READ|SelectionKey.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(SelectionKey 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 = "199.18.24.212";  
  19.   String proxyPort = "8090";  
  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.  }  
Java代码  收藏代码
  1. public class RecvThread extends Thread {  
  2.   public SocketChannel sc = null;  
  3.   
  4.   public boolean val = true;  
  5.   
  6.   public RecvThread(String str, SocketChannel client) {  
  7.    super(str);  
  8.    sc = client;  
  9.   }  
  10.   
  11.   public void run() {  
  12.    int nBytes = 0;  
  13.    ByteBuffer buf = ByteBuffer.allocate(2048);  
  14.    try {  
  15.     while (val) {  
  16.      while ((nBytes = nBytes = client.read(buf)) > 0) {  
  17.       buf.flip();  
  18.       Charset charset = Charset.forName("us-ascii");  
  19.       CharsetDecoder decoder = charset.newDecoder();  
  20.       CharBuffer charBuffer = decoder.decode(buf);  
  21.       String result = charBuffer.toString();  
  22.       System.out.println("the server return: " + result);  
  23.       buf.flip();  
  24.   
  25.      }  
  26.     }  
  27.   
  28.    } catch (IOException e) {  
  29.     e.printStackTrace();  
  30.   
  31.    }  
  32.   
  33.   }  
  34.  }  
  35. }  


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。 

Java代码  收藏代码
  1. IoThreadPoolFilter threadPool = new IoThreadPoolFilter();threadPool.start();  
  2. IoAcceptor acceptor = new SocketAcceptor();  
  3. acceptor.getFilterChain().addLast( "threadPool", threadPool);  
  4. ProtocolThreadPoolFilter threadPool2 = new ProtocolThreadPoolFilter();  
  5. threadPool2.start();  
  6. ProtocolAcceptor acceptor2 = new IoProtocolAcceptor( acceptor );  
  7. acceptor2.getFilterChain().addLast( "threadPool", threadPool2 );  
  8. ...  
  9. threadPool2.stop();  
  10. threadPool.stop();  




采用MINA进行socket开发,一般步骤如下: 
1: 
server: 

Java代码  收藏代码
  1. IoAcceptor acceptor = new SocketAcceptor(); //建立client接收器  


or client: 

Java代码  收藏代码
  1. SocketConnector connector = new SocketConnector();  //建立一个连接器  


2:server的属性配置: 
     

Java代码  收藏代码
  1. SocketAcceptorConfig cfg = new SocketAcceptorConfig();  
  2.       cfg.setReuseAddress(true);  
  3.       cfg.getFilterChain().addLast(  
  4.                   "codec",  
  5.                   new ProtocolCodecFilter( new ObjectSerializationCodecFactory() ) ); //对象序列化 codec factory  
  6.       cfg.getFilterChain().addLast( "logger"new LoggingFilter() );  


3:绑定address和business logic 
server: 
      

Java代码  收藏代码
  1. acceptor.bind(  
  2.                new InetSocketAddress( SERVER_PORT ),  
  3.                new ServerSessionHandler( ), cfg ); // 绑定address和handler  



client: 
      

Java代码  收藏代码
  1. connector.connect(new InetSocketAddress( HOSTNAME, PORT ),  
  2.                        new ClientSessionHandler(msg), cfg );  



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

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



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

原文地址:https://www.cnblogs.com/suifengbingzhu/p/2649674.html