Mina框架学习笔记(二)

来源:互联网 发布:unity3d中播放视频 编辑:程序博客网 时间:2024/04/30 05:43

上一篇只写了一个服务端。这一次来构建一个客户端。

 

首先,在引入 上一篇中讲到的几个jar包处,还要引入一个mina-example-2.0.0.jar

 

本程序的主要功能是,客户端向服务器发送几个数字,然后服务器给客户端 返回结果。文字就不多写了,我在上面都写了注释!

 

下面的服务端代码:

[java] view plaincopy
  1. import java.io.IOException;  
  2. import java.net.InetSocketAddress;  
  3. import org.apache.mina.example.sumup.codec.SumUpProtocolCodecFactory;  
  4. import org.apache.mina.filter.codec.ProtocolCodecFilter;  
  5. import org.apache.mina.filter.codec.serialization.ObjectSerializationCodecFactory;  
  6. import org.apache.mina.filter.logging.LoggingFilter;  
  7. import org.apache.mina.transport.socket.nio.NioSocketAcceptor;  
  8. public class MinaServer {  
  9.     private static final int PORT = 8389,BUF_SIZE = 2048;  
  10.     // Set this to false to use object serialization instead of custom codec.  
  11.     private static final boolean USE_CUSTOM_CODEC = true;  
  12.     public static void main(String[] args) throws IOException {  
  13.         NioSocketAcceptor acceptor = new NioSocketAcceptor();  
  14.           
  15.         // Add 'codec' filter  
  16.         if(USE_CUSTOM_CODEC){  
  17.             acceptor.getFilterChain().addLast("codec",  
  18.                     new ProtocolCodecFilter(  
  19.                             new SumUpProtocolCodecFactory(false)));  
  20.         } else {  
  21.             acceptor.getFilterChain().addLast("codec",  
  22.                     new ProtocolCodecFilter(  
  23.                             new ObjectSerializationCodecFactory()));  
  24.         }  
  25.           
  26.         //This filter will log all information such as newly created   
  27.             //sessions, messages received, messages sent, session closed  
  28.         acceptor.getFilterChain().addLast("logger"new LoggingFilter());  
  29.           
  30.         acceptor.setHandler(new MinaServerHandler());  
  31.           
  32.         acceptor.getSessionConfig().setReadBufferSize(BUF_SIZE);  
  33.         //the first parameter defines what actions to check for when   
  34.             //determining if a session is idle, the second parameter defines   
  35.             //the length of time in seconds that must occur before a session   
  36.             //is deemed to be idle.  
  37.         //acceptor.getSessionConfig().setIdleTime(IdleStatus.BOTH_IDLE, 60);  
  38.           
  39.         acceptor.bind(new InetSocketAddress(PORT));  
  40.         System.out.println("Listening on port:"+PORT);  
  41.           
  42.     }  
  43. }  
 

 

它使用到了一个自定义的Handler来管理连接过程中的各个事件,代码如下:

[java] view plaincopy
  1. import org.apache.mina.core.service.IoHandlerAdapter;  
  2. import org.apache.mina.core.session.IdleStatus;  
  3. import org.apache.mina.core.session.IoSession;  
  4. import org.apache.mina.example.sumup.ServerSessionHandler;  
  5. import org.apache.mina.example.sumup.message.AddMessage;  
  6. import org.apache.mina.example.sumup.message.ResultMessage;  
  7. import org.slf4j.Logger;  
  8. import org.slf4j.LoggerFactory;  
  9. public class MinaServerHandler extends IoHandlerAdapter {  
  10.     private static final String SUM_KEY = "sum";  
  11.     private final static Logger LOGGER = LoggerFactory.getLogger(ServerSessionHandler.class);  
  12.       
  13.     @Override  
  14.     public void exceptionCaught(IoSession session, Throwable cause)  
  15.             throws Exception {  
  16.         session.close(true);  
  17.         cause.printStackTrace();  
  18.     }  
  19.     @Override  
  20.     public void messageReceived(IoSession session, Object message)  
  21.             throws Exception {  
  22.         // client only sends AddMessage. otherwise, we will have to identify  
  23.         // its type using instanceof operator.  
  24.         AddMessage am = (AddMessage) message;  
  25.           
  26.         //Add the value to the current sum.  
  27.         int sum = ((Integer) session.getAttribute(SUM_KEY)).intValue();  
  28.         int value = am.getValue();  
  29.         long expectedSum = (long) sum+value;  
  30.           
  31.         if(expectedSum > Integer.MAX_VALUE || expectedSum < Integer.MIN_VALUE){  
  32.             //If the sum overflows or underflows , return error message.  
  33.             ResultMessage rMessage = new ResultMessage();  
  34.             rMessage.setSequence(am.getSequence()); // copy sequence  
  35.             rMessage.setOk(false);  
  36.             session.write(rMessage);  
  37.         } else {  
  38.             //sum up  
  39.             sum = (int) expectedSum;  
  40.             session.setAttribute(SUM_KEY,new Integer(sum));  
  41.               
  42.             //return the result message.  
  43.             ResultMessage rmMessage = new ResultMessage();  
  44.             rmMessage.setSequence(am.getSequence()); //copy sequece  
  45.               
  46.             rmMessage.setOk(true);  
  47.             rmMessage.setValue(sum);  
  48.             session.write(rmMessage);  
  49.         }  
  50.     }  
  51.     @Override  
  52.     public void messageSent(IoSession session, Object message) throws Exception {  
  53.         System.out.println("Message sent:"+message);  
  54.     }  
  55.     @Override  
  56.     public void sessionIdle(IoSession session, IdleStatus status)  
  57.             throws Exception {  
  58.         LOGGER.info("Disconnecting the idle...");  
  59.         //disconnect an idle client  
  60.         session.close(true);  
  61.     }  
  62.     @Override  
  63.     public void sessionOpened(IoSession session) throws Exception {  
  64.         //Set idle time to 60 seconds  
  65.         session.getConfig().setIdleTime(IdleStatus.BOTH_IDLE, 60);  
  66.           
  67.         //Initial sum is 0  
  68.         session.setAttribute(SUM_KEY,new Integer(0));  
  69.     }  
  70. }  
 

 

接下去就是客户端了。一样的,先写一个主类,然后再写一上Handler来管理事件。

 

[java] view plaincopy
  1. import java.net.InetSocketAddress;  
  2. import org.apache.mina.core.RuntimeIoException;  
  3. import org.apache.mina.core.future.ConnectFuture;  
  4. import org.apache.mina.core.session.IoSession;  
  5. import org.apache.mina.example.sumup.codec.SumUpProtocolCodecFactory;  
  6. import org.apache.mina.filter.codec.ProtocolCodecFilter;  
  7. import org.apache.mina.filter.codec.serialization.ObjectSerializationCodecFactory;  
  8. import org.apache.mina.filter.logging.LoggingFilter;  
  9. import org.apache.mina.transport.socket.nio.NioSocketConnector;  
  10. public class MinaClient {  
  11.     private final static long DEF_TIMEOUT = 60*1000L; //1 minute      
  12.     // Set this to false to use object serialization instead of custom codec.  
  13.     private static final boolean USE_CUSTOM_CODEC = true;  
  14.     // Server and port  
  15.     private static final int PORT = 8389;  
  16.     private static final String SERVER = "127.0.0.1";  
  17.     private static IoSession session;  
  18.       
  19.     /** 
  20.      * @param args 
  21.      * @throws InterruptedException  
  22.      */  
  23.     public static void main(String[] args) throws InterruptedException {  
  24.         if (args.length == 0) {  
  25.            System.out.println("Please specify the list of any integers");  
  26.            return;  
  27.         }  
  28.           
  29.         //prepare values to sum up  
  30.         int len = args.length;  
  31.         int[] values = new int[len];  
  32.         for(int i = 0; i < len; i ++){  
  33.             values[i] = Integer.parseInt(args[i]);   
  34.         }  
  35.           
  36.         // Create TCP/IP connector.  
  37.         NioSocketConnector connector = new NioSocketConnector();  
  38.           
  39.         //Set connect timeout  
  40.         connector.setConnectTimeoutMillis(DEF_TIMEOUT);  
  41.           
  42.         // Add 'codec' filter  
  43.         if(USE_CUSTOM_CODEC){  
  44.             connector.getFilterChain().addLast("codec",  
  45.                     new ProtocolCodecFilter(  
  46.                             new SumUpProtocolCodecFactory(false)));  
  47.         } else {  
  48.             connector.getFilterChain().addLast("codec",  
  49.                     new ProtocolCodecFilter(  
  50.                             new ObjectSerializationCodecFactory()));  
  51.         }  
  52.           
  53.         connector.getFilterChain().addLast("logger"new LoggingFilter());  
  54.         //Start communication  
  55.         connector.setHandler(new NetCatProtocolHandler(values));  
  56.           
  57.         //If it fails to connect to the server,  
  58.         //retry it after 10 seconds!  
  59.         while(true){  
  60.             try{  
  61.                 ConnectFuture future = connector.connect(new InetSocketAddress(SERVER,PORT));  
  62.                 future.awaitUninterruptibly();  
  63.                 session = future.getSession();  
  64.                 break;  
  65.             } catch (RuntimeIoException e) {  
  66.                 System.err.println("Fail to connect!");  
  67.                 e.printStackTrace();  
  68.                 Thread.sleep(10*1000L);  
  69.             }  
  70.         }  
  71.           
  72.         //Wait for the connection attempt to be finished.  
  73.         session.getCloseFuture().awaitUninterruptibly();  
  74.           
  75.         connector.dispose();  
  76.     }  
  77. }  
 

 

Handler类

[java] view plaincopy
  1. import org.apache.mina.core.service.IoHandlerAdapter;  
  2. import org.apache.mina.core.session.IdleStatus;  
  3. import org.apache.mina.core.session.IoSession;  
  4. import org.apache.mina.example.sumup.ClientSessionHandler;  
  5. import org.apache.mina.example.sumup.message.AddMessage;  
  6. import org.apache.mina.example.sumup.message.ResultMessage;  
  7. import org.slf4j.LoggerFactory;  
  8. public class NetCatProtocolHandler extends IoHandlerAdapter {  
  9.       
  10.     private int[] values;     
  11.     private boolean finished;  
  12.     private static final org.slf4j.Logger LOGGER = LoggerFactory.getLogger(ClientSessionHandler.class);  
  13.       
  14.     // provide a method for other class to judge whether it's finished.  
  15.     public boolean isFinished() {  
  16.         return finished;  
  17.     }  
  18.     public NetCatProtocolHandler(int[] values) {  
  19.         this.values = values;  
  20.     }  
  21.     @Override  
  22.     public void exceptionCaught(IoSession session, Throwable cause)  
  23.             throws Exception {  
  24.         session.close(true);  
  25.     }  
  26.     @Override  
  27.     public void messageReceived(IoSession session, Object message)  
  28.             throws Exception {  
  29. //      IoBuffer buffer = (IoBuffer) message;         
  30. //      while(buffer.hasRemaining()){  
  31. //          System.out.println(buffer.getChar());  
  32. //      }         
  33. //      System.out.flush();  
  34.           
  35.           
  36.         // server only sends ResultMessage. otherwise, we will have to identify  
  37.         // its type using instanceof operator.  
  38.         ResultMessage rm = (ResultMessage)message;  
  39.         if(rm.isOk()){  // server returned OK code.           
  40.             // if received the result message which has the last sequence  
  41.             // number, it is time to disconnect.  
  42.             if(rm.getSequence() == values.length - 1){  
  43.                 //Print the sum and disconnect.  
  44.                 LOGGER.warn("Server error, disconnecting...");  
  45.                 session.close(true);  
  46.                   
  47.                 finished = true;  
  48.             }  
  49.         }  
  50.     }  
  51.     @Override  
  52.     public void messageSent(IoSession session, Object message) throws Exception {  
  53.         session.write(message);  
  54.         System.out.println("Message sent:"+message);  
  55.     }  
  56.     @Override  
  57.     public void sessionClosed(IoSession session) throws Exception {  
  58.         System.err.println("Total "+ session.getReadBytes()+" byte(s)");  
  59.     }  
  60.     @Override  
  61.     public void sessionIdle(IoSession session, IdleStatus status)  
  62.             throws Exception {  
  63.         if(status == IdleStatus.READER_IDLE) {  
  64.             session.close(true);  
  65.         }  
  66.     }  
  67.     @Override  
  68.     public void sessionOpened(IoSession session) throws Exception {  
  69.         // Set reader idle time to 60 seconds.  
  70.         // sessionIdle(...) method will be invoked when no data is read  
  71.         // for 60 seconds.  
  72.         //session.getConfig().setIdleTime(IdleStatus.READER_IDLE, 60);  
  73.           
  74.         // send summation requests  
  75.         for(int i = 0; i < values.length; i ++){  
  76.             AddMessage message = new AddMessage();  
  77.             message.setSequence(i);  
  78.             message.setValue(values[i]);  
  79.               
  80.             session.write(message);  
  81.         }  
  82.     }  
  83.       
  84. }