你的位置:首页 > 操作系统

[操作系统]Android使用Apach Mina入门读书(一)

最近开发一个项目需要用到Client(Android)透过Socket与Server通讯,网上有看到Apache封装好的Socket通讯包,初步学习。

内容主要来源于(MINA官方教程(中文版))

1.网络应用架构:

基于ApacheMINA的网络应用有三个层次,分别是I/O服务、I/O过滤器和I/O处理器:
I/O服务:I/O服务用来执行实际的I/O操作。ApacheMINA已经提供了一系列支持不同协议的I/O服务,如TCP/IP、UDP/IP、串口和虚拟机内部的管道等。开发人员也可以实现自己的I/O服务。
I/O过滤器:I/O服务能够传输的是字节流,而上层应用需要的是特定的对象与数据结构。
   I/O过滤器用来完成这两者之间的转换。I/O过滤器的另外一个重要作用是对输入输出的数据进行处理,满足横切的需求。多个I/O过滤器串联起来,形成I/O过滤器链。
I/O处理器:I/O处理器用来执行具体的业务逻辑。对接收到的消息执行特定的处理。创建一个完整的基于ApacheMINA的网络应用,需要分别构建这三个层次。

2.完成Client代码初始化四步骤:

    //第一步:创建连接对象:
    SocketConnector connector = new NioSocketConnector();
   
     //第二步:给该连接对象设置处理对象:(IoHandlerAdapter)
    ClientHandler handler = new ClientHandler();
    connector.setHandler(handler);
  

    // 第三步:添加过滤器:
    connector.getFilterChain().addLast("codec",
        new ProtocolCodecFilter(new TextLineCodecFactory(Charset.forName("UTF-8"),
            LineDelimiter.WINDOWS.getValue(), LineDelimiter.WINDOWS.getValue())));   


    //第四步:绑定即将通信对象:
    connector.connect(new InetSocketAddress("192.168.1.101", 5260));

3. I/O服务(IoService是I/O服务的接口,继承 IoAcceptor)

I/O服务用来执行真正的I/O操作,以及管理I/O会话。根据所使用的数据传输方式的不同,有不同的I/O服务的实现。由于I/O服务执行的是输入和输出两种操作,实际上有两种具体的子类型。一种称为“I/O接受器(I/Oacceptor)”,用来接受连接,一般用在服务器的实现中;另外一种称为“I/O连接器(I/Oconnector)”,用来发起连接,一般用在客户端的实现中。

表1.IoService中的重要方法方法说明
setHandler(IoHandlerhandler):设置I/O处理器。该I/O处理器会负责处理该I/O服务所管理的所有I/O会话产生的I/O事件。getFilterChain()获取I/O过滤器链,可以对I/O过滤器进行管理,包括添加和删除I/O过滤器。
getManagedSessions():获取该I/O服务所管理的I/O会话。

I/O连接器 Code Example:

SocketConnectorconnector=newNioSocketConnector();

connector.setConnectTimeoutMillis(CONNECT_TIMEOUT);
connector.getFilterChain().addLast("logger",newLoggingFilter());

connector.getFilterChain().addLast("protocol",
newProtocolCodecFilter(newTetrisCodecFactory()));
ConnectFutureconnectFuture=connector.connect(newInetSocketAddress(host,port));

connectFuture.awaitUninterruptibly();

4.I/O会话(IoSession)

I/O会话表示一个活动的网络连接,与所使用的传输方式无关。I/O会话可以用来存储用户自定义的与应用相关的属性。这些属性通常用来保存应用的状态信息,还可以用来在I/O过滤器和I/O处理器之间交换数据。I/O会话在作用上类似于Servlet规范中的HTTP会话。

表2.IoSession中的重要方法方法说明:
close(booleanimmediately):关闭当前连接。如果参数immediately为true的话,连接会等到队列中所有的数据发送请求都完成之后才关闭;否则的话就立即关闭。
getAttribute(Objectkey):从I/O会话中获取键为key的用户自定义的属性。
setAttribute(Objectkey,Objectvalue):将键为key,值为value的用户自定义的属性存储到I/O会话中。
removeAttribute(Objectkey):从I/O会话中删除键为key的用户自定义的属性。
write(Objectmessage):将消息对象message发送到当前连接的对等体。该方法是异步的,当消息被真正发送到对等体的时候,IoHandler.messageSent(IoSession,Object)会被调用。如果需要的话,也可以等消息真正发送出去之后再继续执行后续操作。

这个接口有如下常用的方法:
A. WriteFuture write(Object message):这个方法用于写数据,该操作是异步的。
B. CloseFuture close(boolean immediately):这个方法用于关闭IoSession,该操作也是异步的,参数指定true 表示立即关闭,否则就在所有的写操作都flush 之后再关闭。
C. Object setAttribute(Object key,Object value):这个方法用于给我们向会话中添加一些属性,这样可以在会话过程中都可以使用,类似于HttpSession 的setAttrbute()方法。IoSession 内部使用同步的HashMap 存储你添加的自定义属性。

5.I/O过滤器(IoFilterAdapter)

从I/O服务发送过来的所有I/O事件和请求,在到达I/O处理器之前,会先由I/O过滤器链中的I/O过滤器进行处理。过滤器可以在很多情况下使用,比如记录日志、性能分析、访问控制、负载均衡和消息转换等。过滤器非常适合满足网络应用中各种横切的非功能性需求。在一个基于ApacheMINA的网络应用中,一般存在多个过滤器。这些过滤器互相串联,形成链条,称为过滤器链。每个过滤器依次对传入的I/O事件进行处理。当前过滤器完成处理之后,由过滤器链中的下一个过滤器继续处理。当前过滤器也可以不调用下一个过滤器,而提前结束,这样I/O事件就不会继续往后传递。比如负责用户认证的过滤器,如果遇到未认证的对等体发出的I/O事件,则会直接关闭连接。这可以保证这些事件不会通过此过滤器到达I/O处理器。

表3.IoFilter中与过滤器的生命周期相关的方法

init():当过滤器第一次被添加到过 滤器链中的时候,此方法被调用。用来完成过滤器的初始化工作。

onPreAdd(IoFilterChainparent,Stringname,IoFilter.NextFilternextFilter): 当过滤器即将被添加到过滤 器链中的时候,此方法被调用。

onPostAdd(IoFilterChainparent,String name,IoFilter.NextFilternextFilter):当过滤器已经被添加到过滤器链中之后,此方法被调用

onPreRemove(IoFilterChainparent,Stringname,IoFilter.NextFilternextFilter):当过滤器即将被从过滤器链中删除的时候,此方法被调用。
onPostRemove(IoFilterChainparent,Stringname,IoFilter.NextFilternextFilter):当过滤器已经被从过滤器链中删除的时候,此方法被调用。
destroy():当过滤器不再需要的时候,它将被销毁,此方法被调用

参数parent表示包含此过滤器的过滤器链,参数name表示过滤器的名称,参数nextFilter表示过滤器链中的下一个过滤器。

filterClose(IoFilter.NextFilternextFilter,IoSessionsession):滤对IoSession的close方法的调用。
filterWrite(IoFilter.NextFilternextFilter,IoSessionsession,WriteRequestwriteRequest):滤对IoSession的write方法的调用。
exceptionCaught(IoFilter.NextFilternextFilter,IoSessionsession,Throwablecause):滤对IoHandler的exceptionCaught方法的调用。

messageReceived(IoFilter.NextFilternextFilter,IoSessionsession,Objectmessage):过滤对IoHandler的messageReceived方法的调用。

messageSent(IoFilter.NextFilternextFilter,IoSessionsession,WriteRequestwriteRequest):过滤对IoHandler的messageSent方法的调用。

sessionClosed(IoFilter.NextFilternextFilter,IoSessionsession):过滤对IoHandler的sessionClosed方法的调用。
sessionCreated(IoFilter.NextFilternextFilter,IoSessionsession):过滤对IoHandler的sessionCreated方法的调用。
sessionIdle(IoFilter.NextFilternextFilter,IoSessionsession,IdleStatusstatus):过滤对IoHandler的sessionIdle方法的调用。

sessionOpened(IoFilter.NextFilternextFilter,IoSessionsession):过滤对IoHandler的sessionOpened方法的调用。

code example:

public void messageReceived(NextFilternextFilter,IoSessionsession,Objectmessage){
if(!isON(session)){
    nextFilter.messageReceived(session,message);

}else{
           endSession(session);

}

}
private void endSession(IoSessionsession){
    session.close(true);

}

6.过滤器链(IoFilterChain)

过滤器只有在添加到过滤器链中的时候才起作用。过滤器链是过滤器的容器。过滤器链与I/O会话是一一对应的关系.

IoFilterChain接口的方法方法说明:
addFirst(String name,IoFilterfilter filter):将指定名称的过滤器添加到过滤器链的开头。
addLast(String name,IoFilterfilter filter):将指定名称的过滤器添加到过滤器链的末尾。

contains(String name)判断过滤器链中是否包含指定名称的过滤器。

get(String name):从过滤器链中获取指定名称的过滤器。

remove(String name):从过滤器链中删除指定名称的过滤器。
replace(String name,IoFilter newFilter):用过滤器newFilter替换掉过滤器链中名为name的过滤器。

getSession():获取与过滤器链一一对应的I/O会话

7.I/O处理器(IoHandlerAdapter)

I/O事件通过过滤器链之后会到达I/O处理器。I/O处理器中与I/O事件对应的方法会被调用。ApacheMINA中org.apache.mina.core.service.IoHandler是I/O处理器要实现的接口,一般情况下,只需要继承自org.apache.mina.core.service.IoHandlerAdapter并覆写所需方法即可。

IoHandler接口的方法:

sessionCreated(IoSessionsession)当有新的连接建立的时候,该方法被调用。

sessionOpened(IoSessionsession)当有新的连接打开的时候,该方法被调用。该方法在sessionCreated之后被调用。
sessionClosed(IoSessionsession)当连接被关闭的时候,此方法被调用。

sessionIdle(IoSessionsession,IdleStatusstatus)当连接变成闲置状态的时候,此方法被调用。
exceptionCaught(IoSessionsession,Throwablecause)当I/O处理器的实现或是ApacheMINA中有异常抛出的时候,此方法被调用。
messageReceived(IoSessionsession,Objectmessage)当接收到新的消息的时候,此方法被调用。

messageSent(IoSessionsession,Objectmessage)当消息被成功发送出去的时候,此方法被调用。

其中

1.sessionCreated和sessionOpened的区别:

sessionCreated方法是由I/O处理线程来调用的,而sessionOpened是由其它线程来调用的。因此从性能方面考虑,不要在sessionCreated方法中执行过多的操作。

2.sessionIdle,默认情况下,闲置时间设置是禁用的,也就是说sessionIdle并不会被调用。可以通过IoSessionConfig.setIdleTime(IdleStatus,int)来进行设置

 

常用方法:

1. WriteFuture的使用
IoSessionsession=...;//获取I/O会话对象
WriteFuturefuture=session.write("HelloWorld");//发送数据

future.awaitUninterruptibly();//等待发送数据操作完成

if(future.isWritten()){
//数据已经被成功发送}else{
//数据发送失败}
由于这样的需求很常见,I/O处理器中提供了messageSent方法,当数据发送成功的时候,该方法会被调用。

2. JMX集成ApacheMINA可以集成JMX来对网络应用进行管理和监测。

MBeanServermBeanServer=ManagementFactory.getPlatformMBeanServer();

IoAcceptoracceptor=newNioSocketAcceptor();
IoServiceMBeanacceptorMBean=newIoServiceMBean(acceptor);

ObjectNameacceptorName=newObjectName(acceptor.getClass().getPackage().getName()+":type=acceptor,name="+acceptor.getClass().getSimpleName));

mBeanServer.registerMBean(acceptorMBean,acceptorName);