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

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

Mina Logo
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 等等。

一、相关资源下载

(1) Apache官方网站:http://mina.apache.org
(2) Android用jar包(包括官网的资源,我会一律放在百度网盘下)

二、Mina简单配置

服务器端一共要用到四个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
如果要使用log4j.jar包,则要在项目的src目录下新建一个log4j.properties,添加内容如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
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

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

三、Mina服务端

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

程序入口文件

新建一个Demo1Server.class文件,里面包含着程序的入口,端口号,Acceptor连接.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
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();
}
}

}

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

消息处理类

新建一个消息处理类,或者说是是业务逻辑处理器——Demo1ServerHandler,它继承了IoHandlerAdapter类,它默认覆盖了七个方法,而我们主要使用messageReceived()。\

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
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服务器框架就搭好了,我们可以使用电脑上的telnet命令来测试一下服务器能否使用
cmd控制台—>telnet <端口号> 如我的服务器ip地为192.168.1.10 那我就写telnet 192.168.1.10 4444 .此时我们可以看到输出日志为
服务器输出日志
此时连接已经创建,我们在输入信息服务器就会对信息进行处理,并给出相应的应答。

四、Mina客户端(Android端)

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
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对象。当然同样需要添加编码解码过滤器和业务逻辑过滤器。
业务逻辑过滤器代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
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的简单搭建就到这里为止了,希望对大家有所帮助。

参考文章:
(1)Apache MiNa 实现多人聊天室
(2)MINA官方教程(中文版)
资源下载:Mina相关资源

文章作者: cpacm
文章链接: http://www.cpacm.net/2015/03/22/Mina框架的学习笔记——Android客户端的实现/
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 cpacm
打赏
  • 微信
  • 支付宝

评论