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();
    }
    } }

    一个很简单的程序入口吧,简单的说就是在服务器上设置一个消息接收器,让它监听从端口传过来的消息并进行处理。那么接下来我们看看怎么进行消息处理。

  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);
    }
    }

    很直白的一段程序,相当于将服务器分成了七个状态,而每个状态都有自己的一套逻辑处理方案。

  3. 至此,一个最简单的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();
    } }

    不知道你们注意到了没,客户端的代码与服务器端的极其相似,不同的是服务器是创建NioSocketAcceptor对象,而客户端是创建NioSocketConnect对象。当然同样需要添加编码解码过滤器和业务逻辑过滤器。

  2. 业务逻辑过滤器代码:

     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);
    }
    }

    方法功能与服务器端一样。测试这里就不做了。可以的话自己写个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相关资源
 
 ========================================
作者:cpacm
出处:(http://www.cpacm.net/2015/03/22/Mina框架的学习笔记——Android客户端的实现/

Mina框架的学习笔记——Android客户端的实现的更多相关文章

  1. Android Mina框架的学习笔记

    Apache MINA(Multipurpose Infrastructure for Network Applications) 是 Apache 组织一个较新的项目,它为开发高性能和高可用性的网络 ...

  2. go微服务框架kratos学习笔记五(kratos 配置中心 paladin config sdk [断剑重铸之日,骑士归来之时])

    目录 go微服务框架kratos学习笔记五(kratos 配置中心 paladin config sdk [断剑重铸之日,骑士归来之时]) 静态配置 flag注入 在线热加载配置 远程配置中心 go微 ...

  3. go微服务框架kratos学习笔记七(kratos warden 负载均衡 balancer)

    目录 go微服务框架kratos学习笔记七(kratos warden 负载均衡 balancer) demo demo server demo client 池 dao service p2c ro ...

  4. DBFlow框架的学习笔记之入门

    什么是DBFlow? dbflow是一款android高性的ORM数据库.可以使用在进行项目中有关数据库的操作.github下载源码 1.环境配置 先导入 apt plugin库到你的classpat ...

  5. Android动画学习笔记-Android Animation

    Android动画学习笔记-Android Animation   3.0以前,android支持两种动画模式,tween animation,frame animation,在android3.0中 ...

  6. jfinal框架教程-学习笔记

    jfinal框架教程-学习笔记 JFinal  是基于 Java  语言的极速  WEB  + ORM  开发框架,其核心设计目标是开发迅速.代码量少.学习简单.功能强大.轻量级.易扩展.Restfu ...

  7. Java框架spring 学习笔记(十八):事务管理(xml配置文件管理)

    在Java框架spring 学习笔记(十八):事务操作中,有一个问题: package cn.service; import cn.dao.OrderDao; public class OrderSe ...

  8. golang日志框架--logrus学习笔记

    golang日志框架--logrus学习笔记 golang标准库的日志框架非常简单,仅仅提供了print,panic和fatal三个函数,对于更精细的日志级别.日志文件分割以及日志分发等方面并没有提供 ...

  9. # go微服务框架kratos学习笔记六(kratos 服务发现 discovery)

    目录 go微服务框架kratos学习笔记六(kratos 服务发现 discovery) http api register 服务注册 fetch 获取实例 fetchs 批量获取实例 polls 批 ...

随机推荐

  1. ansible-3

    setup ansible_all_ipv4_addresses # ipv4的所有地址 ansible_all_ipv6_addresses # ipv6的所有地址 ansible_date_tim ...

  2. Atom使用插件精选(FE)

    [转]原文https://zhuanlan.zhihu.com/p/24753739?refer=AlenQi Atom琳琅满目的插件中,为前端coder推荐一些实用的插件. sync-setting ...

  3. laravel5.5中间件

    目录 1. 中间件知识 1. artisan 命令 2. 文件内容 3. 前置中间件和后置中间件 4. 使用中间件 2. 控制器中间件 1. 中间件知识 1. artisan 命令 php artis ...

  4. 《Cracking the Coding Interview》——第17章:普通题——题目1

    2014-04-28 21:45 题目:就地交换两个数,不使用额外的变量. 解法:没说是整数,我姑且先当整数处理吧.就地交换可以用加法.乘法.异或完成,其中乘法和加法都存在溢出问题.三种方法都不能处理 ...

  5. wxPython 安装 及参考文档

    三种操作平台上的安装方法 1.windows 和 mac pip install -U wxPython 2.linux pip install -U -f https://extras.wxpyth ...

  6. 【志银】NYOJ《题目529》flip

    题目:flip 题目链接:http://acm.nyist.net/JudgeOnline/problem.php?pid=529 吐槽Time: 由于此题槽点太多,所以没忍住... 看到这题通过率出 ...

  7. 斐波那契数列的三种C++实现及时间复杂度分析

    本文介绍了斐波那契数列的三种C++实现并详细地分析了时间复杂度. 斐波那契数列定义:F(1)=1, F(2)=1, F(n)=F(n-1) + F(n-2) (n>2) 如何计算斐波那契数 F( ...

  8. 团队项目-第八次scrum 会议

    时间:11.4 时长:30分钟 地点:F楼2层沙发休息处 工作情况 团队成员 已完成任务 待完成任务 解小锐 修复员工招聘时bug 完成员工commit函数的数值函数编写 陈鑫 实现雇佣与解雇功能的界 ...

  9. 【linux】如何解决VMWare上linux虚拟机连不上外网的问题?

    >>>故障现象:虚拟机连接不到外网? >>>故障背景: Centos7.4发行版本: 虚拟机和VM软件都是nat模式: 注意这里默认的VMWare的DHCP服务时开 ...

  10. JavaScript中的parseInt和Number函数

    函数作用: parseInt将字符串(String)类型转为整数类型. Number() 函数把对象(Object)的值转换为数字. 语法不同: parseInt(string, [radix]) s ...