Mina 各组件介绍
上一篇文章已经系统的介绍了 Mina 的运行流程,Apache 推出的 Mina 性能上很是高效,上章节我们知道内部有很多的类,各个类之间的依赖也是很多,他们之家都是相互依赖。
下面主要看看各个类中的方法。本篇就当是 Mina 的文档了。一下总结来源于网络:
IoService
-
这个接口是服务端 IoAcceptor、客户端 IoConnector 的抽象,提供 IO 服务和管理 IoSession 的功能,它有如下几个常用的方法:
-
<font color=”blue”>TransportMetadata getTransportMetadata()</font>:
这个方法获取传输方式的元数据描述信息,也就是底层到底基于什么的实现,譬如:nio、apr 等。
-
<font color=”blue”>void addListener(IoServiceListener listener)</font>:
这个方法可以为 IoService 增加一个监听器,用于监听 IoService 的创建、活动、失效、空闲、销毁,具体可以参考 IoServiceListener 接口中的方法,这为你参与 IoService 的生命周期提供了机会。
-
<font color=”blue”>void removeListener(IoServiceListener listener)</font>:
这个方法用于移除上面的方法添加的监听器。
-
<font color=”blue”>void setHandler(IoHandler handler)</font>:
这个方法用于向 IoService 注册 IoHandler,同时有 getHandler()方法获取 Handler。
-
<font color=”blue”>Map<Long,IoSession> getManagedSessions()</font>:
这个方法获取 IoService 上管理的所有 IoSession,Map 的 key 是 IoSession 的 id。
-
<font color=”blue”>IoSessionConfig getSessionConfig()</font>:
这个方法用于获取 IoSession 的配置对象,通过 IoSessionConfig 对象可以设置 Socket 连接的一些选项。
-
IoAcceptor
- IoAcceptor 主要就是 bind 方法。之前文章已经介绍过了。这里一带而过
IoConnector
- 这个接口是 TCPClient 的接口,主要增加了 ConnectFuture connect(SocketAddressremoteAddress,SocketAddress localAddress)方法,用于与 Server 端建立连接,第二个参数如果不传递则使用本地的一个随机端口访问 Server 端。这个方法是异步执行的,同样的,也可以同时连接多个服务端。
IoSession
-
这个接口用于表示 Server 端与 Client 端的连接,IoAcceptor.accept()的时候返回实例。
- <font color=”blue”>WriteFuture write(Object message)</font>
用于异步写数据
- <font color=”blue”>CloseFuture close(boolean immediately)</font>
这个方法用于关闭 IoSession,该操作也是异步的,参数指定 true 表示立即关闭,否则就在所有的写操作都 flush 之后再关闭
- <font color=”blue”>Object setAttribute(Object key,Object value)</font>
这个方法用于给我们向会话中添加一些属性,这样可以在会话过程中都可以使用,类似于 HttpSession 的 setAttrbute()方法。IoSession 内部使用同步的 HashMap 存储你添加的自
定义属性。 - <font color=”blue”>SocketAddress getRemoteAddress()</font>
这个方法获取远端连接的套接字地址
- <font color=”blue”>void suspendWrite()</font>
这个方法用于挂起写操作,那么有 void resumeWrite()方法与之配对。对于 read()方法同样适用
- <font color=”blue”> ReadFuture read()</font>
这个方法用于读取数据,但默认是不能使用的,你需要调用 IoSessionConfig 的 setUseReadOperation(true)才可以使用这个异步读取的方法。一般我们不会用到这个方法,因为这个方法的内部实现是将数据保存到一个 BlockingQueue,假如是 Server 端,因为大量的 Client 端发送的数据在 Server 端都这么读取,那么可能会导致内存泄漏,但对于 Client,可能有的时候会比较便利
- <font color=”blue”> IoService getService()</font>
这个方法返回与当前会话对象关联的 IoService 实例. 关于 TCP 连接的关闭:无论在客户端还是服务端,IoSession 都用于表示底层的一个 TCP 连接,那么你会发现无论是 Server 端还是 Client 端的 IoSession 调用 close()方法之后,TCP 连接虽然显示关闭,但主线程仍然在运行,也就是 JVM 并未退出,这是因为 IoSession 的 close()仅仅是关闭了 TCP 的连接通道,并没有关闭 Server 端、Client 端的程序。你需要调用 IoService 的 dispose()方法停止 Server 端、Client 端
- <font color=”blue”>WriteFuture write(Object message)</font>
IoSessionConfig
-
这个方法用于指定此次会话的配置,它有如下常用的方法
-
<font color=”blue”> void setReadBufferSize(int size)</font>
这个方法设置读取缓冲的字节数,但一般不需要调用这个方法,因为 IoProcessor 会自动调整缓冲的大小。你可以调用 setMinReadBufferSize()、setMaxReadBufferSize()方法,这样无论 IoProcessor 无论如何自动调整,都会在你指定的区间
-
<font color=”blue”>void setIdleTime(IdleStatus status,int idleTime)</font>
这个方法设置关联在通道上的读、写或者是读写事件在指定时间内未发生,该通道就进入空闲状态。一旦调用这个方法,则每隔 idleTime 都会回调过滤器、IoHandler 中的 sessionIdle()方法
-
<font color=”blue”> void setWriteTimeout(int time)</font>
这个方法设置写操作的超时时间
-
<font color=”blue”>void setUseReadOperation(boolean useReadOperation)</font>
这个方法设置 IoSession 的 read()方法是否可用,默认是 false
-
IoHandler
-
这个接口是你编写业务逻辑的地方,从上面的示例代码可以看出,读取数据、发送数据基本都在这个接口总完成,这个实例是绑定到 IoService 上的,有且只有一个实例(没有给一个 IoService 注入一个 IoHandler 实例会抛出异常)。它有如下几个方法
- <font color=”blue”>void sessionCreated(IoSession session)</font>
这个方法当一个 Session 对象被创建的时候被调用。对于 TCP 连接来说,连接被接受的时候调用,但要注意此时 TCP 连接并未建立,此方法仅代表字面含义,也就是连接的对象 IoSession 被创建完毕的时候,回调这个方法。对于 UDP 来说,当有数据包收到的时候回调这个方法,因为 UDP 是无连接的
- <font color=”blue”>void sessionOpened(IoSession session)</font>
这个方法在连接被打开时调用,它总是在 sessionCreated()方法之后被调用。对于 TCP 来说,它是在连接被建立之后调用,你可以在这里执行一些认证操作、发送数据等。对于 UDP 来说,这个方法与 sessionCreated()没什么区别,但是紧跟其后执行。如果你每隔一段时间,发送一些数据,那么 sessionCreated()方法只会在第一次调用,但是 sessionOpened()方法每次都会调用
- <font color=”blue”>void sessionClosed(IoSession session)</font>
对于 TCP 来说,连接被关闭时,调用这个方法。对于 UDP 来说,IoSession 的 close()方法被调用时才会毁掉这个方法
- <font color=”blue”>void sessionIdle(IoSession session, IdleStatus status)</font>
这个方法在 IoSession 的通道进入空闲状态时调用,对于 UDP 协议来说,这个方法始终不会被调用
- <font color=”blue”>void exceptionCaught(IoSession session, Throwable cause)</font>
这个方法在你的程序、Mina 自身出现异常时回调,一般这里是关闭 IoSession
- <font color=”blue”>void messageReceived(IoSession session, Object message)</font>
接收到消息时调用的方法,也就是用于接收消息的方法,一般情况下,message 是一个 IoBuffer 类,如果你使用了协议编解码器,那么可以强制转换为你需要的类型。通常我们都是会使用协议编解码器的,就像上面的例子,因为协议编解码器是 TextLineCodecFactory,所以我们可以强制转 message 为 String 类型
- <font color=”blue”>void messageSent(IoSession session, Object message)</font>
当发送消息成功时调用这个方法,注意这里的措辞,发送成功之后,也就是说发送消息是不能用这个方法的。发送消息的时机:发送消息应该在 sessionOpened()、messageReceived()方法中调用 IoSession.write()方法完成。因为在 sessionOpened()方法中,TCP 连接已经真正打开,同样的在 messageReceived()方法 TCP 连接也是打开状态,只不过两者的时机不同。sessionOpened()方法是在 TCP 连接建立之后,接收到数据之前发送;messageReceived()方法是在接收到数据之后发送,你可以完成依据收到的内容是什么样子,决定发送什么样的数据。因为这个接口中的方法太多,因此通常使用适配器模式 IoHandlerAdapter,覆盖你所感兴趣的方法即可
- <font color=”blue”>void sessionCreated(IoSession session)</font>
IoBuffer
-
这个接口是对 JAVA NIO 的 ByteBuffer 的封装,这主要是因为 ByteBuffer 只提供了对基本数据类型的读写操作,没有提供对字符串等对象类型的读写方法,使用起来更为方便,另外,ByteBuffer 是定长的,如果想要可变,将很麻烦。IoBuffer 的可变长度的实现类似于 StringBuffer。IoBuffer 与 ByteBuffer 一样,都是非线程安全的。本节的一些内容如果不清楚,可以参考 java.nio.ByteBuffer 接口。这个接口有如下常用的方法
-
<font color=”blue”>static IoBuffer allocate(int capacity,boolean useDirectBuffer)</font>
这个方法内部通过 SimpleBufferAllocator 创建一个实例,第一个参数指定初始化容量,第二个参数指定使用直接缓冲区还是 JAVA 内存堆的缓存区,默认为 false
-
<font color=”blue”>void free()</font>
释放缓冲区,以便被一些 IoBufferAllocator 的实现重用,一般没有必要调用这个方法,除非你想提升性能(但可能未必效果明显)
-
<font color=”blue”>IoBuffer setAutoExpand(boolean autoExpand)</font>
这个方法设置 IoBuffer 为自动扩展容量,也就是前面所说的长度可变,那么可以看出长度可变这个特性默认是不开启的
-
<font color=”blue”>IoBuffer setAutoShrink(boolean autoShrink)</font>
这个方法设置 IoBuffer 为自动收缩,这样在 compact()方法调用之后,可以裁减掉一些没有使用的空间。如果这个方法没有被调用或者设置为 false,你也可以通过调用 shrink()方法手动收缩空间
-
<font color=”blue”>IoBuffer order(ByteOrder bo)</font>
这个方法设置是 Big Endian 还是 Little Endian,JAVA 中默认是 Big Endian,C++ 和其他语言一般是 Little Endian
-
<font color=”blue”>IoBuffer asReadOnlyBuffer()</font>
这个方法设置 IoBuffer 为只读的
-
<font color=”blue”>Boolean prefixedDataAvailable(int prefixLength,int maxDataLength)</font>
这个方法用于数据的最开始的 1、2、4 个字节表示的是数据的长度的情况,prefixLentgh 表示这段数据的前几个字节(只能是 1、2、4 的其中一个),代表的是这段数据的长度,maxDataLength 表示最多要读取的字节数。返回结果依赖于等式 remaining()-prefixLength>=maxDataLength,也就是总的数据 - 表示长度的字节,剩下的字节数要比打算读取的字节数大或者相等
-
<font color=”blue”>String getPrefixedString(int prefixLength,CharsetDecoder decoder)</font>
如果上面的方法返回 true,那么这个方法将开始读取表示长度的字节之后的数据,注意要保持这两个方法的 prefixLength 的值是一样的。G、H 两个方法在后面讲到的 PrefixedStringDecoder 中的内部实现使用。IoBuffer 剩余的方法与 ByteBuffer 都是差不多的,额外增加了一些便利的操作方法,例如:IoBuffer putString(String value,CharsetEncoder encoder)可以方便的以指定的编码方式存储字符串、InputStream asInputStream()方法从 IoBuffer 剩余的未读的数据中转为输入流等
-
IoFuture
-
在 Mina 的很多操作中,你会看到返回值是 XXXFuture,实际上他们都是 IoFuture 的子类,看到这样的返回值,这个方法就说明是异步执行的,主要的子类有 ConnectFuture、CloseFuture、ReadFuture、WriteFuture。这个接口的大部分操作都和 java.util.concurrent.Future 接口是类似的,譬如:await()、awaitUninterruptibly()等,一般我们常用 awaitUninterruptibly()方法可以等待异步执行的结果返回。这个接口有如下常用的方法
-
<font color=”blue”>IoFuture addListener(IoFutureListener<?> listener)</font>
这个方法用于添加一个监听器,在异步执行的结果返回时监听器中的回调方法 operationComplete(IoFuture future),也就是说,这是替代 awaitUninterruptibly()方法另一种等待异步执行结果的方法,它的好处是不会产生阻塞
-
<font color=”blue”>IoFuture removeListener(IoFutureListener<?> listener)</font>
这个方法用于移除指定的监听器
-
<font color=”blue”>IoSession getSession()
这个方法返回当前的 IoSession。举个例子,我们在客户端调用 connect()方法访问 Server 端的时候,实际上这就是一个异步执行的方法,也就是调用 connect()方法之后立即返回,执行下面的代码,而不管是否连接成功。那么如果我想在连接成功之后执行一些事情(譬如:获取连接成功后的 IoSession 对象),该怎么办呢?按照上面的说明,你有如下两种办法:
-
加入战队
<span id=”addMe”> 加入战队 </span>
微信公众号
主题
加入战队
<span id=”addMe”> 加入战队 </span>
微信公众号