JAVA NIO异步通信框架MINA选型和使用的几个细节(概述入门,UDP, 心跳)

<转http://blog.csdn.net/doliu6/article/details/5863502>

Apache MINA 2 是一个开发高性能和高可伸缩性网络应用程序的网络应用框架。它提供了一个抽象的事件驱动的异步 API,可以使用 TCP/IP、UDP/IP、串口和虚拟机内部的管道等传输方式。Apache MINA 2 可以作为开发网络应用程序的一个良好基础。

    Apache MINA是非常著名的基于java nio的通信框架,以前都是自己直接使用udp编程,新项目选型中考虑到网络通信可能会用到多种通信方式,因此使用了MINA。

     本文结构:

     (1)客户端和服务器代码;虽然是udp的,但是mina的优美的设计使得所有的通信方式能够以统一的形式使用,perfect。当然注意的是,不同的通信方式,背后的机理和有效的变量、状态是有区别的,所以要精通,那还是需要经验积累和学习的。

     (2)超时和Session的几个实际问题

     (3)心跳,纠正几个错误

     既然是使用,废话少说,直接整个可用的例子。当然了,这些代码也不是直接可用的,我们应用的逻辑有点复杂,不会这么简单使用的。

请参考mina的example包和文档http://mina.apache.org/udp-tutorial.html

版本2.0 RC1

1.1 服务器端

  1.                 NioDatagramAcceptor acceptor = new NioDatagramAcceptor(); 
  2.                 acceptor.setHandler(new MyIoHandlerAdapter());//你的业务处理,最简单的,可以extends IoHandlerAdapter 
  3.  
  4. DefaultIoFilterChainBuilder chain = acceptor.getFilterChain(); 
  5. chain.addLast("keep-alive", new HachiKeepAliveFilterInMina()); //心跳 
  6. chain.addLast("toMessageTyep", new MyMessageEn_Decoder());  
  7.               //将传输的数据转换成你的业务数据格式。比如下面的是将数据转换成一行行的文本 
  8.                 //acceptor.getFilterChain().addLast("codec",new ProtocolCodecFilter(new TextLineCodecFactory(Charset.forName("UTF-8"))));  
  9.  
  10. chain.addLast("logger", new LoggingFilter()); 
  11. DatagramSessionConfig dcfg = acceptor.getSessionConfig(); 
  12. dcfg.setReuseAddress(true); 
  13. acceptor.bind(new InetSocketAddress(ClusterContext.getHeartBeatPort())); 

1.2 客户端

  1.               NioDatagramConnector connector = new NioDatagramConnector(); 
  2. connector.setConnectTimeoutMillis(60000L); 
  3. connector.setConnectTimeoutCheckInterval(10000); 
  4. connector.setHandler(handler); 
  5.  
  6. DefaultIoFilterChainBuilder chain = connector.getFilterChain(); 
  7. chain.addLast("keep-alive", new HachiKeepAliveFilterInMina());//心跳 
  8. chain.addLast("toMessageTyep", new MyMessageEn_Decoder()); 
  9. chain.addLast("logger", new LoggingFilter()); 
  10. ConnectFuture connFuture = connector.connect(new InetSocketAddress("10.1.1.1",8001)); 
  11. connFuture.awaitUninterruptibly(); 
  12. IoSession session = connFuture.getSession(); 
  13.                 //发送消息长整型 1000 
  14.               IoBuffer buffer = IoBuffer.allocate(8); 
  15.               buffer.putLong(1000); 
  16.               buffer.flip(); 
  17.               session.write(buffer); 
  18.                  //关闭连接 
  19.                  session.getCloseFuture().awaitUninterruptibly(); 
  20. connector.dispose(); 

2. 超时的几个经验总结:

    udp session默认是60秒钟超时,此时状态为closing,数据就发不出去了。

Session的接口是IoSession,udp的最终实现是NioSession。如果交互在60秒内不能处理完成,就需要使用Keep-alive机制,即心跳机制。

3. 心跳机制

    在代码中已经使用了心跳机制,是通过mina的filter实现的,mina自身带的心跳机制好处在于,它附加了处理,让心跳消息不会传到业务层,在底层就完成了。

    在上面代码实现中的HachiKeepAliveFilterInMina如下:

    

  1. public class HachiKeepAliveFilterInMina extends KeepAliveFilter { 
  2.     private static final int INTERVAL = 30;//in seconds 
  3.     private static final int TIMEOUT = 10; //in seconds 
  4.      
  5.     public HachiKeepAliveFilterInMina(KeepAliveMessageFactory messageFactory) { 
  6.         super(messageFactory, IdleStatus.BOTH_IDLE, new ExceptionHandler(), INTERVAL, TIMEOUT); 
  7.     } 
  8.      
  9.     public HachiKeepAliveFilterInMina() { 
  10.         super(new KeepAliveMessageFactoryImpl(), IdleStatus.BOTH_IDLE, new ExceptionHandler(), INTERVAL, TIMEOUT); 
  11.         this.setForwardEvent(false); //此消息不会继续传递,不会被业务层看见 
  12.     } 
  13.  
  14. class ExceptionHandler implements KeepAliveRequestTimeoutHandler {    
  15.     public void keepAliveRequestTimedOut(KeepAliveFilter filter, IoSession session) throws Exception {    
  16.         System.out.println("Connection lost, session will be closed");    
  17.         session.close(true);  
  18.     }    
  19.  
  20. /**
  21. * 继承于KeepAliveMessageFactory,当心跳机制启动的时候,需要该工厂类来判断和定制心跳消息
  22. * @author Liu Liu
  23. *
  24. */ 
  25. class KeepAliveMessageFactoryImpl implements KeepAliveMessageFactory { 
  26.     private static final byte int_req = -1
  27.     private static final byte int_rep = -2;  
  28.     private static final IoBuffer KAMSG_REQ = IoBuffer.wrap(new byte[]{int_req});    
  29.     private static final IoBuffer KAMSG_REP = IoBuffer.wrap(new byte[]{int_rep});   
  30.         
  31.     public Object getRequest(IoSession session) {    
  32.         return KAMSG_REQ.duplicate();    
  33.     }    
  34.  
  35.     public Object getResponse(IoSession session, Object request) {    
  36.         return KAMSG_REP.duplicate();    
  37.     }    
  38.  
  39.     public boolean isRequest(IoSession session, Object message) {   
  40.         if(!(message instanceof IoBuffer)) 
  41.             return false
  42.         IoBuffer realMessage = (IoBuffer)message; 
  43.         if(realMessage.limit() != 1
  44.             return false
  45.          
  46.         boolean result = (realMessage.get() == int_req); 
  47.         realMessage.rewind(); 
  48.         return result; 
  49.     }    
  50.  
  51.     public boolean isResponse(IoSession session, Object message) {     
  52.         if(!(message instanceof IoBuffer)) 
  53.             return false
  54.         IoBuffer realMessage = (IoBuffer)message; 
  55.         if(realMessage.limit() != 1
  56.             return false
  57.          
  58.         boolean result = (realMessage.get() == int_rep);    
  59.         realMessage.rewind(); 
  60.         return result; 
  61.     }    

  有人说:心跳机制的filter只需要服务器端具有即可——这是错误的,拍着脑袋想一想,看看factory,你就知道了。心跳需要通信两端的实现

  另外,版本2.0 RC1中,经过测试,当心跳的时间间隔INTERVAL设置为60s(Session的存活时间)的时候心跳会失效,所以最好需要小于60s的间隔。

更多可参考:

http://www.ibm.com/developerworks/cn/java/j-lo-mina2

以上只是初步使用的一点经验,2和3的部分很难在网上找到,所以分享出来,因为时间关系、可能有些偏颇或者错误,望指正交流。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值