Apache MINA(Multipurpose Infrastructure for Network Applications) 是 Apache 组织一个较新的项目,它是一个网络通信应用框架,为开发高性能和高可用性的网络应用程序提供了非常便利的框架。
也就是说,它主要是对基于TCP/IP、UDP/IP协议栈的通信框架(当然,也可以提供JAVA 对象的序列化服务、虚拟机管道通信服务等)。
Mina 可以帮助我们快速开发高性能、高扩展性的网络通信应用,Mina 提供了事件驱动、异步(Mina 的异步IO 默认使用的是JAVA NIO 作为底层支持)操作的编程模型。
Mina 主要有1.x 和2.x 两个分支,这里我们讲解最新版本2.0,如果你使用的是Mina 1.x,那么可能会有一些功能并不适用。学习Mina,需要你已掌握JAVA IO、JAVA NIO、JAVASocket、JAVA 线程及并发库(java.util.concurrent.*)的知识。
Mina 同时提供了网络通信的Server 端、Client 端的封装。无论是哪端,Mina 在整个网通通信结构中都处于如下的位置:可见Mina 的API 将真正的网络通信与我们的应用程序隔离开来,你只需要关心你要发送、接收的数据以及你的业务逻辑即可。
同样的,无论是哪端,Mina 的执行流程如下所示:
2. Mina总体框架基于MINA框架的应用程序架构应该是这样的:
Mina的核心部分架构Mina的底层是基于JAVA的NIO 1.0实现的,其核心部分架构是这样的:
Mina的内部的3个层次- I/O Service - 执行实际的I / O,可以选择现成的Services如 (*Acceptor),也可以自己写。
- I/O Filter Chain - 这是一个由多个过滤器组成的过滤器链,在这个环节将字节数据转换到特定的数据结构中(Filters/Transforms bytes into desired Data Structures and vice-versa)
- I/O Handler - 实际的业务逻辑部分
对socket通信来说,使用比较广泛的是基于Server端的应用,尤其是并发规模达到一定程度后,颇具挑战性。
那么我们来看一下,基于MINA框架的Server端应用:
- IOAcceptor 监听指定的端口,处理新的网络连接;一旦一个新的连接到达后,IOAcceptor 就产生一个session,后续所有从这个IP和端口发送过来的请求就将通过这个Session被处理。
- Session创建后,后续所有的数据包都被人到过滤器链中,通过过滤器将原始的字节码转变成高层的对象,这个环节PacketEncoder/Decoder就十分有用。
- 最后数据包或对象被传送给Handler做业务逻辑处理;
Mina.java
package com.hl.magic.mina;
import org.apache.mina.core.service.IoAcceptor;
import org.apache.mina.core.session.IdleStatus;
import org.apache.mina.filter.codec.ProtocolCodecFilter;
import org.apache.mina.filter.codec.textline.TextLineCodecFactory;
import org.apache.mina.filter.logging.LoggingFilter;
import org.apache.mina.transport.socket.nio.NioSocketAcceptor;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.charset.StandardCharsets;
public class Mina {
private static final int PORT = 54321;
public static boolean connect() {
try {
IoAcceptor acceptor = new NioSocketAcceptor();
acceptor.getFilterChain().addLast("logger", new LoggingFilter());
acceptor.getFilterChain().addLast("codec", new ProtocolCodecFilter(new TextLineCodecFactory(StandardCharsets.UTF_8)));
acceptor.setHandler(new TimeServerHandler());
acceptor.getSessionConfig().setReadBufferSize(2048);
acceptor.getSessionConfig().setIdleTime(IdleStatus.BOTH_IDLE, 10);
acceptor.bind(new InetSocketAddress(PORT));
return true;
} catch (IOException e) {
e.printStackTrace();
return false;
}
}
public static void main(String[] args) {
boolean connect = connect();
System.out.println("连接:" + connect);
}
}
- 创建IoAcceptor;
- 加入日志记录和解码的过滤器,其中日志过滤器用SL4J库记录信息,而编码过滤器则解码所有收到的信息。使用 new TextLineCodecFactory() 发送的信息迕行编码,返是MINA自带的,功能有限,只能处理文本戒者String类型。
- 设置ServerHandler,这里是一个自定义的Handler:TimeServerHandler;
- 设置Session的对应的I/O processor 读缓存区大小2048;通常这个参数不需要设置;
- 设置空闲时间,这里的BOTH_IDLE指EADER_IDLE 和 WRITER_IDLE. 都为10秒;
- 绑定监听端口9123;
TimeServerHandler.java:
package com.hl.magic.mina;
import org.apache.mina.core.service.IoHandlerAdapter;
import org.apache.mina.core.session.IdleStatus;
import org.apache.mina.core.session.IoSession;
import java.util.Date;
public class TimeServerHandler extends IoHandlerAdapter {
@Override
public void exceptionCaught(IoSession session, Throwable cause) {
cause.printStackTrace();
}
@Override
public void messageReceived(IoSession session, Object message) {
String str = message.toString();
if (str.trim().equalsIgnoreCase("quit")) {
session.close();
return;
}
Date date = new Date();
session.write(date.toString());
System.out.println("Message written...");
}
@Override
public void sessionIdle(IoSession session, IdleStatus status) {
System.out.println("IDLE " + session.getIdleCount(status));
}
}
这里主要有一下几个主要的方法:
messageReceived(…),对接收到的消息(已经解码)迕行下一步处理,这里对收到的字符串进行判断,如果是”quit”则断开连接;否则输出当前时间的字符串格式;
exceptionCaught(…),自定义异常处理, 要不然异常会被“吃掉”;
sessionIdle,当Session处于IDLE状态的时候,输出空闲状态次数;
测试,运行CMD,在窗口输入:telnet 127.0.0.1 54321
然后在CMD窗口上随便输入一串字符串,显示当前的时间:



