Android Mina框架的学习笔记


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包(包括官网的资源,我会一律放在百度网盘下)

二、Mina简单配置

1.服务器端一共要用到四个jar包,包括一个日志包。将他们放在lib中,并加载进去
分别为 mina-core-2.0.7.jar slf4j-log4j12-1.7.6.jar slf4j-api-1.7.6.jar log4j-1.2.14.jar(日志管理包)
2.如果要使用日志的jar包,则要在项目的src目录下新建一个log4j.properties,添加内容如下:

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

3.Android客户端要加入的jar包:mina-core-2.0.7.jar  slf4j-android-1.6.1-RC1.jar 两个jar包(可能直接使用上面的jar包也会行,我没试过~)

二、Mina服务端

我这边使用的是mina2.0版本,所以可能与mina1.0的版本有所不同。那么首先在服务器端创建开始

  1. 新建一个Demo1Server.class文件,里面包含着程序的入口,端口号,Acceptor连接.
public class Demo1Server {
    //日志类的实现
    private static Logger logger = Logger.getLogger(Demo1Server.class);
    //端口号,要求客户端与服务器端一致
    private static int PORT = 4444;

    public static void main(String[] args){
        IoAcceptor acceptor = null;
        try{
            //创建一个非阻塞的server端的Socket
            acceptor = new NioSocketAcceptor();
            //设置过滤器(使用mina提供的文本换行符编解码器)
            acceptor.getFilterChain().addLast("codec", new ProtocolCodecFilter(new TextLineCodecFactory(Charset.forName("UTF-8"),LineDelimiter.WINDOWS.getValue(),LineDelimiter.WINDOWS.getValue())));
            //自定义的编解码器
            //acceptor.getFilterChain().addLast("codec", new ProtocolCodecFilter(new CharsetCodecFactory()));
            //设置读取数据的换从区大小
            acceptor.getSessionConfig().setReadBufferSize(2048);
            //读写通道10秒内无操作进入空闲状态
            acceptor.getSessionConfig().setIdleTime(IdleStatus.BOTH_IDLE, 10);
            //为接收器设置管理服务
            acceptor.setHandler(new Demo1ServerHandler());
            //绑定端口
            acceptor.bind(new InetSocketAddress(PORT));

            logger.info("服务器启动成功...    端口号未:"+PORT);

        }catch(Exception e){
            logger.error("服务器启动异常...",e);
            e.printStackTrace();
        }
    }

}
  1. 一个很简单的程序入口吧,简单的说就是在服务器上设置一个消息接收器,让它监听从端口传过来的消息并进行处理。那么接下来我们看看怎么进行消息处理。
  2. 新建一个消息处理类,或者说是是业务逻辑处理器——Demo1ServerHandler,它继承了IoHandlerAdapter类,它默认覆盖了七个方法,而我们主要使用messageReceived()。
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);
    }
}
  1. 很直白的一段程序,相当于将服务器分成了七个状态,而每个状态都有自己的一套逻辑处理方案。
  2. 至此,一个最简单的Mina服务器框架就搭好了,我们可以使用电脑上的telnet命令来测试一下服务器能否使用
    cmd控制台—>telnet <ip地址> <端口号>  如我的服务器ip地为192.168.1.10  那我就写telnet 192.168.1.10 4444 .此时我们可以看到输出日志为

    此时连接已经创建,我们在输入信息服务器就会对信息进行处理,并给出相应的应答。
    (telnet的用法不知道的可以自行百度)

、Mina客户端(Android端)

1.服务器简单搭建完毕,那么开始在Android端是配置服务器吧。同样的不要忘记加载jar包, 由于Android自带了Logout,所以就不使用Mina的日志包了。
由于接受消息会阻塞Android的进程,所以我把它开在子线程中(同时将其放在Service中,让其在后台运行)

public class MinaThread extends Thread {

    private IoSession session = null;

    @Override
    public void run() {
        // TODO Auto-generated method stub
        Log.d("TEST","客户端链接开始...");
        IoConnector connector = new NioSocketConnector();
        //设置链接超时时间
        connector.setConnectTimeoutMillis(30000);
        //添加过滤器
        //connector.getFilterChain().addLast("codec", new ProtocolCodecFilter(new CharsetCodecFactory()));
        connector.getFilterChain().addLast("codec", new ProtocolCodecFilter(new TextLineCodecFactory(Charset.forName("UTF-8"),LineDelimiter.WINDOWS.getValue(),LineDelimiter.WINDOWS.getValue())));
        connector.setHandler(new MinaClientHandler(minaService));

        try{
            ConnectFuture future = connector.connect(new InetSocketAddress(ConstantUtil.WEB_MATCH_PATH,ConstantUtil.WEB_MATCH_PORT));//创建链接
            future.awaitUninterruptibly();// 等待连接创建完成
            session = future.getSession();//获得session
            session.write("start");
        }catch (Exception e){
            Log.d("TEST","客户端链接异常...");
        }
        session.getCloseFuture().awaitUninterruptibly();//等待连接断开
        Log.d("TEST","客户端断开...");
        connector.dispose();
        super.run();
    }

}
  1. public class MinaClientHandler extends IoHandlerAdapter{
    
        @Override
        public void exceptionCaught(IoSession session, Throwable cause)
                throws Exception {
            Log.d("TEST","客户端发生异常");
            super.exceptionCaught(session, cause);
        }
    
        @Override
        public void messageReceived(IoSession session, Object message)
                throws Exception {
            String msg = message.toString();
            Log.d("TEST","客户端接收到的信息为:" + msg);
            super.messageReceived(session, message);
        }
    
        @Override
        public void messageSent(IoSession session, Object message) throws Exception {
            // TODO Auto-generated method stub
            super.messageSent(session, message);
        }
    }
    1. 方法功能与服务器端一样。测试这里就不做了。可以的话自己写个Demo效果更好

    、Mina的更多功能

    1. 拿到所有客户端Session

      Collection<IoSession> sessions = session.getService().getManagedSessions().values();
    2. 自定义编码解码器,可以对消息进行预处理。要继承ProtocolEncoder和ProtocolDecode类。
    3. 数据对象的传递

    这些功能不便放在这里讲了,可能我会以后再找机会另开一篇来讲述这些功能~,大家可以浏览结尾处的参考文章来加深对mina的理解。

    在我认为,熟悉和快速使用一个新的的框架可以看出一个程序员的水平,同样及时总结和归纳自己学到的新知识也是一个好的程序员该具有的习惯。那么Mina的简单搭建就到这里为止了,希望对大家有所帮助。
     
    参考文章:(1)Apache MiNa 实现多人聊天室  http://www.cnblogs.com/hoojo/archive/2012/08/01/2617857.html
                (2)MINA官方教程(中文版)    (百度
    资源下载:Mina相关资源
     
时间: 2024-10-09 06:41:44

Android Mina框架的学习笔记的相关文章

Mina框架的学习笔记——Android客户端的实现

Apache MINA(Multipurpose Infrastructure for Network Applications) 是 Apache 组织一个较新的项目,它为开发高性能和高可用性的网络应用程序提供了非常便利的框架.当前发行的 MINA 版本支持基于 Java NIO 技术的 TCP/UDP 应用程序开发.串口通讯程序(只在最新的预览版中提供),MINA 所支持的功能也在进一步的扩展中.目前正在使用 MINA 的软件包括有:Apache Directory Project.Asyn

Android网络框架OKhttp3学习笔记

OKhttp3是一个非常强大的Android网络框架,它是由Square公司开发并开源的,很大Android开发者都会使用到,所以我也要来学学. 服务器 为了方便测试,我们需要一个后台服务器的的应用,下面是一个Java Web的Servlet,它的功能是接收客户端发来的登录数据,判断密码是否正确,并返回结果(JSON格式) import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; impo

Android(java)学习笔记233: 远程服务的应用场景(移动支付案例)

一. 移动支付:       用户需要在移动终端提交账号.密码以及金额等数据 到 远端服务器.然后远端服务器匹配这些信息,进行逻辑判断,进而完成交易,返回交易成功或失败的信息给移动终端.用户提交账号.密码以及金额等数据都是比较敏感的数据,这些数据不能让外界获取.       阿里等等支付宝平台把支付的逻辑封装起来,只给我们提供一个方法去调用,这样提高了安全性.当我们用户提交账号.密码以及金额等数据,点击"支付"的时候,支付宝平台已经调用方法加密数据(这个支付逻辑是远程服务,为了安全,防

node.js框架StrongLoop学习笔记(一)

node.js框架StrongLoop学习笔记(一) 本人在用node.js做手机后台,查找框架发现StrongLoop挺适合,可是却发现没有中文教程,于是在自己学习时,做一下笔记,以方便其他像我一样的人参考(本人的英语水平非常差,只能一点点试着做,并记录下来,如果大家发现问题,请通知我好更正,谢谢了!).所有操作都是在CentOS7-x64,Node.js 0.12.2下完成的. nodejs框架StrongLoop学习笔记一 安装StrongLoop 创建项目 安装数据库驱动 配置数据库连接

[转载]Android Bitmap和Canvas学习笔记

http://blog.chinaunix.net/uid-20771867-id-3053339.html [转载]Android Bitmap和Canvas学习笔记,布布扣,bubuko.com

Android(java)学习笔记167:Java中操作文件的类介绍

1.File类:对硬盘上的文件和目录进行操作的类.    File类是文件和目录路径名抽象表现形式  构造函数:        1) File(String pathname)       Creates a new File instance by converting the given pathname string into an abstract pathname. 2)File(File parent, String child)       Creates a new File i

Android(java)学习笔记205:网易新闻客户端应用编写逻辑过程

1.我们的项目需求是编写一个新闻RSS浏览器,RSS(Really Simple Syndication)是一种描述和同步网站内容的格式,是使用最广泛的XML应用.RSS目前广泛用于网上新闻频道,blog和wiki,主要的版本有0.91, 1.0, 2.0.使用RSS订阅能更快地获取信息,网站提供RSS输出,有利于让用户获取网站内容的最新更新.网络用户可以在客户端借助于支持RSS的聚合工具软件,在不打开网站内容页面的情况下阅读支持RSS输出的网站内容. 例如如下的网易RSS订阅: 2.由于我们这

Android(java)学习笔记204:自定义SmartImageView(继承自ImageView,扩展功能为自动获取网络路径图片)

1.有时候Android系统配置的UI控件,不能满足我们的需求,Android开发做到了一定程度,多少都会用到自定义控件,一方面是更加灵活,另一方面在大数据量的情况下自定义控件的效率比写布局文件更高. 2.下面我们是自定义一个SmartImageView继承自ImageView,扩展了ImageView的功能:     步骤: • 新建一个SmartImageView类,让继承自ImageView(放置特定的包下): • 实现SmartImageView类下的构造方法,最好全部实现,这个不容易出

Android(java)学习笔记227:服务(service)之服务的生命周期(service)

1.之前我们在Android(java)学习笔记171:Service生命周期 (2015-08-18 10:56)说明过,可以回头看看: 2.接下来就简单概括性描述一下: (1)start的方式开启服务,服务会执行onCreate方法 (2)如果服务已经被创建,就不会再去执行onStartCommand()  (onStart过时) (3)停止服务,服务会执行onDestory(): (4)如果服务已经停止,多次调用stopService()无效的