一、Mina框架。
Mina的框架大概是这么个样子:
底层由Java 的NIO 1.0实现 核心架构应该是这样:
内部有三个层次:
I/O Service:实际执行的 I / O ,可以选择现成的Services 如 Acceptor 也可以自己实现。
I/O Filter Chain :由多个过滤器组成的过滤器链,在这个环节将字节过滤或转换为预想的数据结构,反之亦然。
I/O Handler :实际的业务逻辑部分。
Server 端应用,创建一个基于 MINA 的应用程序,主要分为三步、
1、Create I/O Service 。IOAcceptor 监听指定的端口,处理网络连接请求;一旦一个新的连接到达,IOAcceptor 产生一个session,后续所有从这个IP和端口发送过来的请求都将被这个Session处理。
2、Create Filter Chain。从现有的Filters 中选择或者创建一个传输 Request / Response 的自定义的Filter 。Session创建之后所有的数据包都被放到过滤器链中,通过过滤器将原始的字节码转变为高层的对象,继承这两个接口完成自己的编码解码 ProtocolEncoderAdapter ProtocolDecoderAdapter
。
3、Create I/O Handler。 最终数据包或者对象被传送给Handler 做业务逻辑处理。
二、IoService。
IoService 是一个接口,两种实现方式:IoAcceptor IoConnector .IoAcceptor是针对Server端,IoConnector 是针对Client端。IoService的主要职责:监听器管理、IoHandler、IoSession管理、FilterChain管理、Statistics 管理
三、IoAcceptor:
主要用于创建新的连接,Mina提供了多种实现,基本不用自己再去实现。
NioSocketAcceptor:无阻塞的Socket 传输 Acceptor 针对TCP。
NioDatagramAcceptor:无阻塞的Socket传输Acceptor 针对UDP。
AprSocketAcceptor:阻塞的Socket 传输 Acceptor 基于 APR。
VmPipeSocketAcceptor :the in VM Acceptor
IoConnector:
针对Client端的Socket连接,也有多种实现。
NioSocketConnector:无阻塞的Socket 传输 Acceptor 针对TCP
NioDatagramConnector:无阻塞的Socket 传输 Acceptor 针对UDP
AprSocketConnector:阻塞的Socket传输Connector 基于 APR
ProxyConnector:支持代理服务的Connector,通过截取连接的请求,并将终端指向代理设置的地址
SerialConnector:针对串口传输的Connector
VmPipeConnector:the in vm Connector
四、Session。任何时候只要有新的连接到来,都会生成一个Session对象,并且保存在内存中,直到断开连接
Session状态包括:
五、IoBuffer。IoBuffer是MINA内部的byte buffer,是对Java NIO ByteBuffer的封装,同时扩展了一些更加实用的方法。
capacity属性描述这个缓冲区最多能缓冲多少个元素,也是Buffer的最大存储元素数,这个值在创建Buffer的时候指定,不能修改。
Limit 是从Buffer中向Channel中写入数据时,limit变量指示还剩多少数据可以读取,在从Channel中读取数据到Buffer 中时,limit变量指定还剩多少空间可以存放数据,position正常情况应该小于等于 limit
Position Buffer实际上也是一个Array,当从Channel 读取数据时,将读出来的数据放进底层array,position 变量用来跟踪截止目前为止已经写入多少数据。它指示如果下次写入Buffer时数据应该进入那个Array位置,比如已经读取10字节,position被置为10,指向array第四个位置。
Mark:一个可以记忆的Position位置的值,调用 reset() 方法时会将Position重置为该索引的值,但是Mark并不总是需要定义,但是需要定义时不能定义为负数,不能大于Position,如果定义了Mark 则该Position 或 Limit 调整为小于Mark值时,Mark将被丢弃。例:
i、初始状态下:
此时position为0,limit和capacity都被设为9;
ii、从Channel中读入4个字节数据到Buffer,这时position指向4(第5个):
iii、在做写操作之前,我们必须调用一次flip()方法,这个方法做了两件重要的事情:
1. 将limit设置到当前的position处。
2. 设置position为0。
iiii、执行写操作后;
iv、执行clear后,position设为0,limit设为capition,mark则丢弃;
IoBuffer是一个抽象类,不能直接实例化,所以使用的时候需要调用allocate 方法进行内存分配
IoBuffer buf = IoBuffer.allocate(len); IoBuffer buf1 = IoBuffer.allocate(len, true);
默认direct 是false,得到 heap buffer,如果是true 得到 direct buffer。
Direct Buffer 不是分配在堆上,不被GC管理(但是java对象归GC管理,所以GC回收了对象,direct申请的空间也会被释放)。
Heap Buffer 分配在堆上,可以理解为byte[]的封装。但是当我们把heap buffer写入Channel时,底层会先构建一个临时DirectBuffer,然后复制heap buffer内容,再把这个 direct buffer写出去,因为 direct buffer写入Channel速度快,但是创建和销毁的代价高,所以在能够重用的地方使用。
IoBuffer允许生成一个自动扩展的buffer,设置 AutoExpand属性实现,
IoBuffer buffer = IoBuffer.allocate(8); buffer.setAutoExpand(true); buffer.putString("12345678", encoder); // Add more to this buffer buffer.put((byte)10);
clear() : limit = capacity position = 0;重置 mark ,不清空数据,而是从头开始存放新的数据,相当于覆盖老数据。
reset():清空数据
remaining() :返回 limit - position的值。
hasRemaining() :判断当前是否有数据,返回position < limit 的boolean 值