zoukankan      html  css  js  c++  java
  • 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

  • 相关阅读:
    社区运营一点事
    从拉动APP下载谈运营
    c#基础学习(0702)之面向对象和方法重写概述
    c#基础学习(0706)之使用虚方法实现多态
    c#基础学习(0703)之string.Format格式化日期
    c#基础学习(0701)之一些简单的方法练习
    c#基础学习(0630)之面向对象总习
    c#基础学习(0629)之导出Excel方法
    c#基础学习(0628)之使用进程打开指定的文件、模拟磁盘打开文件
    c#基础学习(0627)之类型转换、算数运算符++、--
  • 原文地址:https://www.cnblogs.com/suifengbingzhu/p/2649674.html
Copyright © 2011-2022 走看看