Apache MINA(Multipurpose Infrastructure for Network Applications) 是 Apache 组织一个较新的项目,它为开发高性能和高可用性的网络应用程序提供了非常便利的框架。当前发行的 MINA 版本支持基于 Java NIO 技术的 TCP/UDP 应用程序开发、串口通讯程序(只在最新的预览版中提供),MINA 所支持的功能也在进一步的扩展中。目前正在使用 MINA 的软件包括有:Apache Directory Project、AsyncWeb、AMQP(Advanced Message Queuing Protocol)、RED5 Server(Macromedia Flash Media RTMP)、ObjectRADIUS、Openfire 等等。
以上是从网上找到的mina框架简单介绍。
由于正在开发的项目中要求加入及时通信功能(游戏方面),所以在网上找了好几种框架,像openfire、tigase等都是基于Xmpp协议开发的优秀框架。但这些侧重于消息的推送,不适合游戏上的简单交互。所以后来找到了mina这个框架,顺手搭建起来。接下来就是这几天学习的总结了,文章里面没有涉及到逻辑层的方面,只是简单的实现即时通信功能。资源下载我会放在文章的最后面。
(1)Apache官方网站:http://mina.apache.org/downloads.html
(2) Android用jar包(包括官网的资源,我会一律放在百度网盘下)
log4j.rootCategory=INFO, stdout , R
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=[QC] %p [%t] %C.%M(%L) | %m%n
log4j.appender.R=org.apache.log4j.DailyRollingFileAppender
log4j.appender.R.File=D:\\Tomcat 5.5\\logs\\qc.log
log4j.appender.R.layout=org.apache.log4j.PatternLayout
1log4j.appender.R.layout.ConversionPattern=%d-[TS] %p %t %c - %m%n
log4j.logger.com.neusoft=DEBUG
log4j.logger.com.opensymphony.oscache=ERROR
log4j.logger.net.sf.navigator=ERROR
log4j.logger.org.apache.commons=ERROR
log4j.logger.org.apache.struts=WARN
log4j.logger.org.displaytag=ERROR
log4j.logger.org.springframework=DEBUG
log4j.logger.com.ibatis.db=WARN
log4j.logger.org.apache.velocity=FATAL
log4j.logger.com.canoo.webtest=WARN
log4j.logger.org.hibernate.ps.PreparedStatementCache=WARN
log4j.logger.org.hibernate=DEBUG
log4j.logger.org.logicalcobwebs=WARN
log4j.rootCategory=INFO, stdout , R
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=[QC] %p [%t] %C.%M(%L) | %m%n
log4j.appender.R=org.apache.log4j.DailyRollingFileAppender
log4j.appender.R.File=D:\\Tomcat 5.5\\logs\\qc.log
log4j.appender.R.layout=org.apache.log4j.PatternLayout
1log4j.appender.R.layout.ConversionPattern=%d-[TS] %p %t %c - %m%n
log4j.logger.com.neusoft=DEBUG
log4j.logger.com.opensymphony.oscache=ERROR
log4j.logger.net.sf.navigator=ERROR
log4j.logger.org.apache.commons=ERROR
log4j.logger.org.apache.struts=WARN
log4j.logger.org.displaytag=ERROR
log4j.logger.org.springframework=DEBUG
log4j.logger.com.ibatis.db=WARN
log4j.logger.org.apache.velocity=FATAL
log4j.logger.com.canoo.webtest=WARN
log4j.logger.org.hibernate.ps.PreparedStatementCache=WARN
log4j.logger.org.hibernate=DEBUG
log4j.logger.org.logicalcobwebs=WARN
二、Mina服务端
我这边使用的是mina2.0版本,所以可能与mina1.0的版本有所不同。那么首先在服务器端创建开始
1 public class Demo1Server { 2 //日志类的实现 3 private static Logger logger = Logger.getLogger(Demo1Server.class); 4 //端口号,要求客户端与服务器端一致 5 private static int PORT = 4444; 6 7 public static void main(String[] args){ 8 IoAcceptor acceptor = null; 9 try{ 10 //创建一个非阻塞的server端的Socket 11 acceptor = new NioSocketAcceptor(); 12 //设置过滤器(使用mina提供的文本换行符编解码器) 13 acceptor.getFilterChain().addLast("codec", new ProtocolCodecFilter(new TextLineCodecFactory(Charset.forName("UTF-8"),LineDelimiter.WINDOWS.getValue(),LineDelimiter.WINDOWS.getValue()))); 14 //自定义的编解码器 15 //acceptor.getFilterChain().addLast("codec", new ProtocolCodecFilter(new CharsetCodecFactory())); 16 //设置读取数据的换从区大小 17 acceptor.getSessionConfig().setReadBufferSize(2048); 18 //读写通道10秒内无操作进入空闲状态 19 acceptor.getSessionConfig().setIdleTime(IdleStatus.BOTH_IDLE, 10); 20 //为接收器设置管理服务 21 acceptor.setHandler(new Demo1ServerHandler()); 22 //绑定端口 23 acceptor.bind(new InetSocketAddress(PORT)); 24 25 logger.info("服务器启动成功... 端口号未:"+PORT); 26 27 }catch(Exception e){ 28 logger.error("服务器启动异常...",e); 29 e.printStackTrace(); 30 } 31 } 32 33 }
一个很简单的程序入口吧,简单的说就是在服务器上设置一个消息接收器,让它监听从端口传过来的消息并进行处理。那么接下来我们看看怎么进行消息处理。
public class Demo1ServerHandler extends IoHandlerAdapter { public static Logger logger = Logger.getLogger(Demo1ServerHandler.class); //从端口接受消息,会响应此方法来对消息进行处理 @Override public void messageReceived(IoSession session, Object message) throws Exception { String msg = message.toString(); if("exit".equals(msg)){ //如果客户端发来exit,则关闭该连接 session.close(true); }
//向客户端发送消息
Date date = new Date();
session.write(date); logger.info("服务器接受消息成功..."); super.messageReceived(session, message); } //向客服端发送消息后会调用此方法 @Override public void messageSent(IoSession session, Object message) throws Exception { logger.info("服务器发送消息成功..."); super.messageSent(session, message); } //关闭与客户端的连接时会调用此方法 @Override public void sessionClosed(IoSession session) throws Exception { logger.info("服务器与客户端断开连接..."); super.sessionClosed(session); } //服务器与客户端创建连接 @Override public void sessionCreated(IoSession session) throws Exception { logger.info("服务器与客户端创建连接..."); super.sessionCreated(session); } //服务器与客户端连接打开 @Override public void sessionOpened(IoSession session) throws Exception { logger.info("服务器与客户端连接打开..."); super.sessionOpened(session); } @Override public void sessionIdle(IoSession session, IdleStatus status) throws Exception { logger.info("服务器进入空闲状态..."); super.sessionIdle(session, status); } @Override public void exceptionCaught(IoSession session, Throwable cause) throws Exception { logger.info("服务器发送异常..."); super.exceptionCaught(session, cause); } }
很直白的一段程序,相当于将服务器分成了七个状态,而每个状态都有自己的一套逻辑处理方案。
三、Mina客户端(Android端)
1 public class MinaThread extends Thread { 2 3 private IoSession session = null; 4 5 @Override 6 public void run() { 7 // TODO Auto-generated method stub 8 Log.d("TEST","客户端链接开始..."); 9 IoConnector connector = new NioSocketConnector(); 10 //设置链接超时时间 11 connector.setConnectTimeoutMillis(30000); 12 //添加过滤器 13 //connector.getFilterChain().addLast("codec", new ProtocolCodecFilter(new CharsetCodecFactory())); 14 connector.getFilterChain().addLast("codec", new ProtocolCodecFilter(new TextLineCodecFactory(Charset.forName("UTF-8"),LineDelimiter.WINDOWS.getValue(),LineDelimiter.WINDOWS.getValue()))); 15 connector.setHandler(new MinaClientHandler(minaService)); 16 17 try{ 18 ConnectFuture future = connector.connect(new InetSocketAddress(ConstantUtil.WEB_MATCH_PATH,ConstantUtil.WEB_MATCH_PORT));//创建链接 19 future.awaitUninterruptibly();// 等待连接创建完成 20 session = future.getSession();//获得session 21 session.write("start"); 22 }catch (Exception e){ 23 Log.d("TEST","客户端链接异常..."); 24 } 25 session.getCloseFuture().awaitUninterruptibly();//等待连接断开 26 Log.d("TEST","客户端断开..."); 27 connector.dispose(); 28 super.run(); 29 } 30 31 }
不知道你们注意到了没,客户端的代码与服务器端的极其相似,不同的是服务器是创建NioSocketAcceptor对象,而客户端是创建NioSocketConnect对象。当然同样需要添加编码解码过滤器和业务逻辑过滤器。
业务逻辑过滤器代码:
1 public class MinaClientHandler extends IoHandlerAdapter{ 2 3 4 @Override 5 public void exceptionCaught(IoSession session, Throwable cause) 6 throws Exception { 7 Log.d("TEST","客户端发生异常"); 8 super.exceptionCaught(session, cause); 9 } 10 11 @Override 12 public void messageReceived(IoSession session, Object message) 13 throws Exception { 14 String msg = message.toString(); 15 Log.d("TEST","客户端接收到的信息为:" + msg); 16 super.messageReceived(session, message); 17 } 18 19 @Override 20 public void messageSent(IoSession session, Object message) throws Exception { 21 // TODO Auto-generated method stub 22 super.messageSent(session, message); 23 } 24 }
方法功能与服务器端一样。测试这里就不做了。可以的话自己写个Demo效果更好
四、Mina的更多功能
Collection<IoSession> sessions = session.getService().getManagedSessions().values();
这些功能不便放在这里讲了,可能我会以后再找机会另开一篇来讲述这些功能~,大家可以浏览结尾处的参考文章来加深对mina的理解。
在我认为,熟悉和快速使用一个新的的框架可以看出一个程序员的水平,同样及时总结和归纳自己学到的新知识也是一个好的程序员该具有的习惯。那么Mina的简单搭建就到这里为止了,希望对大家有所帮助。 参考文章:(1)Apache MiNa 实现多人聊天室 http://www.cnblogs.com/hoojo/archive/2012/08/01/2617857.html (2)MINA官方教程(中文版) (百度) 资源下载:Mina相关资源 ======================================== 作者:cpacm