1.概述
ApacheMINA是一个网络应用程序框架,用来帮助用户简单地开发高性能和高可扩展性的网络应用程序。它提供了一个通过Java NIO在不同的传输例如TCP/IP和UDP/IP上抽象的事件驱动的异步API。
2.Mina几个重要接口:
IoServiece :这个接口在一个线程上负责套接字的建立,拥有自己的 Selector,监听是否有连接被建立。
IoProcessor :这个接口在另一个线程上负责检查是否有数据在通道上读写,也就是说它也拥有自己的 Selector,这是与我们使用 JAVA NIO 编码时的一个不同之处,通常在 JAVA NIO 编码中,我们都是使用一个 Selector,也就是不区分 IoService与 IoProcessor 两个功能接口。另外,IoProcessor 负责调用注册在 IoService 上的过滤器,并在过滤器链之后调用 IoHandler。
IoAccepter :相当于网络应用程序中的服务器端
IoConnector :相当于客户端
IoSession :当前客户端到服务器端的一个连接实例
IoHandler :这个接口负责编写业务逻辑,也就是接收、发送数据的地方。这也是实际开发过程中需要用户自己编写的部分代码。
IoFilter :过滤器用于悬接通讯层接口与业务层接口,这个接口定义一组拦截器,这些拦截器可以包括日志输出、黑名单过滤、数据的编码(write 方向)与解码(read 方向)等功能,其中数据的 encode与 decode是最为重要的、也是你在使用 Mina时最主要关注的地方。
3.IO分为三层
1.IO Service :负责处理IO。
2.IO Fiter Chain :处理编码,字节到数据结构或数据结构到字节的转换等,即非业务逻辑的操作。
3.IO Handle : 负责处理业务逻辑。
4.客户端的通信过程:
1.通过SocketConnector同服务器建立连接。
2.连接建立之后IO的读写交给了IO Processor线程,IO Processor是多线程的。
3.通过IO Processor读取的数据经过IO FiterChain 里所有配置的IO Filter 进行消息的过滤,格式的转换,在这个层面上可以定制一些自定义的协议。
4.最后IO Filter 将数据交给Handle进行业务处理,完成了整个读取的过程。
5.写入的过程也是类似,只是刚好倒过来,通过IOSession.write写出数据,然后Handler完成后交给IO FilterChain ,进行消息过滤和协议的转换,最后通过IO Processor 将数据写出到socket通道。
#5.MINA框架进行开发
首先定义一个业务逻辑处理器TimeServerHandler,继承自IoHandlerAdapter,实现的功能有:当客户端创建会话时会显示客户端设备的IP和端口;当客户端输入quit时结束会话;客户端输入其它内容时则向客户端发送当前时间。
创建服务器:
import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.charset.Charset;
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;
public class MinaTimeServer {
// 定义监听端口
private static final int PORT = 6488;
public static void main(String[] args) throws IOException {
// 创建服务端监控线程
IoAcceptor acceptor = new NioSocketAcceptor();
acceptor.getSessionConfig().setReadBufferSize(2048);
acceptor.getSessionConfig().setIdleTime(IdleStatus.BOTH_IDLE, 10);
// 设置日志记录器
acceptor.getFilterChain().addLast("logger", new LoggingFilter());
// 设置编码过滤器
acceptor.getFilterChain().addLast(
"codec",
new ProtocolCodecFilter(new TextLineCodecFactory(Charset.forName("UTF-8"))));
// 指定业务逻辑处理器
acceptor.setHandler(new TimeServerHandler());
// 设置端口号
acceptor.bind(new InetSocketAddress(PORT));
// 启动监听线程
acceptor.bind();
}
}
服务器端业务逻辑
import org.apache.mina.core.service.IoHandlerAdapter;
import org.apache.mina.core.session.IdleStatus;
import org.apache.mina.core.session.IoSession;
/**
* 服务器端业务逻辑
*/
public class TimeServerHandler extends IoHandlerAdapter {
/**
* 连接创建事件
*/
@Override
public void sessionCreated(IoSession session){
// 显示客户端的ip和端口
System.out.println(session.getRemoteAddress().toString());
}
@Override
public void exceptionCaught(IoSession session, Throwable cause) throws Exception {
cause.printStackTrace();
}
/**
* 消息接收事件
*/
@Override
public void messageReceived(IoSession session, Object message) throws Exception {
String strMsg = message.toString();
if (strMsg.trim().equalsIgnoreCase("quit")) {
session.close(true);
return;
}
// 返回消息字符串
session.write("Hi Client!");
// 打印客户端传来的消息内容
System.out.println("Message written : " + strMsg);
}
@Override
public void sessionIdle(IoSession session, IdleStatus status) throws Exception {
System.out.println("IDLE" + session.getIdleCount(status));
}
}
客户端:
import java.net.InetSocketAddress;
import java.nio.charset.Charset;
import org.apache.mina.core.future.ConnectFuture;
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.NioSocketConnector;
public class MinaTimeClient {
public static void main(String[] args){
// 创建客户端连接器.
NioSocketConnector connector = new NioSocketConnector();
connector.getFilterChain().addLast("logger", new LoggingFilter());
connector.getFilterChain().addLast("codec",
new ProtocolCodecFilter(new TextLineCodecFactory(Charset.forName("UTF-8"))));
// 设置连接超时检查时间
connector.setConnectTimeoutCheckInterval(30);
connector.setHandler(new TimeClientHandler());
// 建立连接
ConnectFuture cf = connector.connect(new InetSocketAddress("192.168.2.109", 6488));
// 等待连接创建完成
cf.awaitUninterruptibly();
cf.getSession().write("Hi Server!");
cf.getSession().write("quit");
// 等待连接断开
cf.getSession().getCloseFuture().awaitUninterruptibly();
// 释放连接
connector.dispose();
}
}
客户端处理逻辑:
import org.apache.mina.core.service.IoHandlerAdapter;
import org.apache.mina.core.session.IoSession;
public class TimeClientHandler extends IoHandlerAdapter {
public void messageReceived(IoSession session, Object message) throws Exception {
String content = message.toString();
System.out.println("client receive a message is : " + content);
}
public void messageSent(IoSession session, Object message) throws Exception {
System.out.println("messageSent -> :" + message);
}
}
总结:
MINA框架完成了底层的线程管理和socket管理;MINA内置的编码器可以满足大多数用户的需求,省去了开发人员消息编码解码的工作。建议在网络应用程序开发过程中尝试使用MINA框架来提高我们的开发效率和应用程序的执行效率。