MINA网络通信框架
Posted by kunshuo on 2012-04-11Leave a comment (1)Go to comments
MINA网络通信框架
基本介绍:
Apache MINA 2是一个开发高性能和高可伸缩性网络应用程序的网络应用框架。它提供了一个抽象的事件驱动的异步API,可以使用TCP/IP、UDP/IP、串口和虚拟机内部的管道等传输方式。Apache MINA 2可以作为开发网络应用程序的一个良好基础。
Mina 的API 将真正的网络通信与我们的应用程序隔离开来,你只需要关心你要发送、
接收的数据以及你的业务逻辑即可。
mina的基本架构:
在图中的模块链中,IoService 便是应用程序的入口,相当于我们前面代码中的 IoAccepter,IoAccepter 便是 IoService 的一个扩展接口。IoService 接口可以用来添加多个 IoFilter,这些 IoFilter 符合责任链模式并由 IoProcessor 线程负责调用。而 IoAccepter 在 ioService 接口的基础上还提供绑定某个通讯端口以及取消绑定的接口。ioHandler则为应用逻辑处理类。
主要类以及接口:
(1.)IoService:这个接口在一个线程上负责套接字的建立,拥有自己的Selector,监
听是否有连接被建立。
(2.)IoProcessor:这个接口在另一个线程上负责检查是否有数据在通道上读写,也就是
说它也拥有自己的Selector,这是与我们使用JAVA NIO编码时的一个不同之处,
通常在JAVA NIO编码中,我们都是使用一个Selector,也就是不区分IoService
与IoProcessor两个功能接口。另外,IoProcessor负责调用注册在IoService上
的过滤器,并在过滤器链之后调用IoHandler。
(3.)IoFilter:这个接口定义一组拦截器,这些拦截器可以包括日志输出、黑名单过滤、
数据的编码(write方向)与解码(read方向)等功能,其中数据的encode与decode
是最为重要的、也是你在使用Mina时最主要关注的地方。 (4.)IoHandler:这个接口负责编写业务逻辑,也就是接收、发送数据的地方。
(5.)IoSession:Session可以理解为服务器与客户端的特定连接,该连接由服务器地址、端口以及客户端地址、端口来决定。客户端发起请求时,指定服务器地址和端口,客户端也会指定或者根据网络路由信息自动指定一个地址、自动分配一个端口。这个地址、端口对构成一个Session。Session是服务器端对这种连接的抽象,MINA对其进行了封装,定义了IoSession接口,用来代表客户端与服务器的连接,在服务器端来指代客户端,实现对客户端的操作、绑定与客户端有关的信息与对象。通过利用Session的这个概念,编写程序时就可以在服务器端非常方便地区分出是当前处理的是哪个客户端的请求、维持客户端的状态信息、可以实现客户端之间相互通讯。
一图胜千言,MINA的核心类图:
服务端代码大致如下:
Java代码
1. //初始化Acceptor—可以不指定线程数量,MINA2里面默认是CPU数量+2
2. //是你的工作主线程
3. NioSocketAcceptor acceptor = new NioSocketAcceptor(5);
4. //建立线程池
5. java.util.concurrent.Executor threadPool = newFixedThreadPool(1500);
6. //加入过滤器(Filter)到Acceptor
7. acceptor.getFilterChain().addLast(“exector”, new ExecutorFilter(threadPool));
8. //编码解码器
9. acceptor.getFilterChain().addLast(“codec”,new ProtocolCodecFilter(new WebDecoder(),new XmlEncoder()));
10. //日志 11. LoggingFilter filter = new LoggingFilter();
12. filter.setExceptionCaughtLogLevel(LogLevel.DEBUG);
13. filter.setMessageReceivedLogLevel(LogLevel.DEBUG);
14. filter.setMessageSentLogLevel(LogLevel.DEBUG);
15. filter.setSessionClosedLogLevel(LogLevel.DEBUG);
16. filter.setSessionCreatedLogLevel(LogLevel.DEBUG);
17. filter.setSessionIdleLogLevel(LogLevel.DEBUG);
18. filter.setSessionOpenedLogLevel(LogLevel.DEBUG);
19. acceptor.getFilterChain().addLast(“logger”, filter);
20. //设置的是主服务监听的端口可以重用
21. acceptor.setReuseAddress(true);
22. //设置每一个非主监听连接的端口可以重用
23. acceptor.getSessionConfig().setReuseAddress(true);
24. //MINA2中,当启动一个服务端的时候,要设定初始化缓冲区的长度,如果不设置这个值,系统默认为2048,当客户端发过来的消息超过设定值的时候,
25. //MINA2的机制是分段接受的,将字符是放入缓冲区中读取,所以在读取消息的时候,需要判断有多少次。这样的好处就是可以节省通讯的流量。
26. //设置输入缓冲区的大小
27. acceptor.getSessionConfig().setReceiveBufferSize(1024);
28. //设置输出缓冲区的大小
29. acceptor.getSessionConfig().setSendBufferSize(10240);
30. //设置为非延迟发送,为true则不组装成大包发送,收到东西马上发出
31. acceptor.getSessionConfig().setTcpNoDelay(true);
32. //设置主服务监听端口的监听队列的最大值为100,如果当前已经有100个连接,再新的连接来将被服务器拒绝
33. acceptor.setBacklog(100);
34. acceptor.setDefaultLocalAddress(new InetSocketAddress(port));
35. //加入处理器(Handler)到Acceptor
36. acceptor.setHandler(new YourHandler());
37. acceptor.bind();
//初始化Acceptor—可以不指定线程数量,MINA2里面默认是CPU数量+2
//是你的工作主线程
NioSocketAcceptor acceptor = new NioSocketAcceptor(5);
//建立线程池
java.util.concurrent.Executor threadPool = newFixedThreadPool(1500);
//加入过滤器(Filter)到Acceptor
acceptor.getFilterChain().addLast("exector", new
ExecutorFilter(threadPool)); //编码解码器
acceptor.getFilterChain().addLast("codec",new ProtocolCodecFilter(new
WebDecoder(),new XmlEncoder()));
//日志
LoggingFilter filter = new LoggingFilter();
filter.setExceptionCaughtLogLevel(LogLevel.DEBUG);
filter.setMessageReceivedLogLevel(LogLevel.DEBUG);
filter.setMessageSentLogLevel(LogLevel.DEBUG);
filter.setSessionClosedLogLevel(LogLevel.DEBUG);
filter.setSessionCreatedLogLevel(LogLevel.DEBUG);
filter.setSessionIdleLogLevel(LogLevel.DEBUG);
filter.setSessionOpenedLogLevel(LogLevel.DEBUG);
acceptor.getFilterChain().addLast("logger", filter);
//设置的是主服务监听的端口可以重用
acceptor.setReuseAddress(true);
//设置每一个非主监听连接的端口可以重用
acceptor.getSessionConfig().setReuseAddress(true);
//MINA2中,当启动一个服务端的时候,要设定初始化缓冲区的长度,如果不设置这个值,系统默认为2048,当客户端发过来的消息超过设定值的时候,
//MINA2的机制是分段接受的,将字符是放入缓冲区中读取,所以在读取消息的时候,需要判断有多少次。这样的好处就是可以节省通讯的流量。
//设置输入缓冲区的大小
acceptor.getSessionConfig().setReceiveBufferSize(1024);
//设置输出缓冲区的大小