mina 实例(转载)
原文:http://maosheng.iteye.com/blog/1891665
Mina 的应用层:

一个设计成熟的开源框架,总是会仅可能的减少侵入性,并在整个项目中找到合适的位置,而不应对整个项目的构架设计产生过多的影响,图 1 就是 MINA 的应用层示意图。从图中和上节的 DEMO 中我们可以看到, MINA很好的把业务代码和底层的通信隔离了开来,我们要做的仅仅是建立好监听,然后写上我们需要实现的业务逻辑就OK 了。
MINA 的内部流程:

(1) IoService :这个接口在一个线程上负责套接字的建立,拥有自己的 Selector ,监听是否有连接被建立。
(2) IoProcessor :这个接口在另一个线程上负责检查是否有数据在通道上读写,也就是说它也拥有自己的Selector ,这是与我们使用 JAVA NIO 编码时的一个不同之处,通常在 JAVA NIO 编码中,我们都是使用一个 Selector ,也就是不区分 IoService 与 IoProcessor 两个功能接口。另外, IoProcessor 也是 MINA 框架的核心组件之一 . 在 MINA 框架启动时,会用一个线程池来专门生成线程,来负责调用注册在 IoService 上的过滤器,并在过滤器链之后调用 IoHandler 。在默认情况 IoProcessor 会用N+1 个线程来轮流询问监视的端口是否有数据传送,其中 n 为 cpu 的内核个数。按一般的多线程设计概念来说,IoProcessor 的线程数是越多越好,但实际上并非如此,因为大家都知道, IO 的操作是非常占用资源的,所以项目中的 IoProcessor 的线程数应该根据实际需要来定,而这个数字可以在生成 IoAcceptor 对象时进行设定。 EgIoAcceptor acceptor = new NioSocketAcceptor( N );
(3.) IoFilter :这个接口定义一组拦截器,这些拦截器可以包括日志输出、黑名单过滤,甚至是在过滤器链中利用 AOP 写上权限控制。数据的编码( write 方向)与解码( read 方向)等功能,其中数据的 encode 与 decode 是最为重要的、也是您在使用 Mina 时最主要关注的地方。
(4.) IoHandler :这个接口负责编写业务逻辑,也就是接收、发送数据的地方。如果大家把业务处理写好,并写好业务接口,真正要用时,只需要在此处替换即可,再次见证了 MINA 分层的彻底。
其中 IoService 接口会专门起一个线程来轮询是否有新的连接产生,一旦有连接产生则通知 IoProcessor, 而IoProcessor 则起 n+1 个线程来检查连接是否有数据在上面读写。一旦有连接产生,并有数据读写,则通知 decode 或 encode ,进行报文的解码或编码,将处理后的报文再交给业务类进行业务处理。其中IoProcessor 是处理请求的分配,包括选择 Selector ,超时验证,状态记录等。总之这个类和 IoService 一起配合工作,封装了 NIO 底层的实现以及 MINA 框架内部的功能的支持 .
结合实例,并根据以上的图文讲解,我们可以很轻易的总结出利用 MINA 编程的几个大致步骤:
创建一个实现了 IoService 接口的类
设置一个实现了 IoFilter 接口的过滤器(如果有需要的情况下)
设置一个 IoHandler 接口实现的处理类,用于处理事件(必须)
对 IoService 绑定一个端口开始工作
注:这一点请特别注意,因 IoProcessor 也是相当于轮询机制,这导致在报文过长时,或其它原因导致报文不能一次传输完毕的情况下,必须保存同一连接 ( 在 MINA 中是以 IoSession 类生成的对象 ) 的上一次状态,这样才能截取到一个完成的报文,而这也是 decode( 编码器 ) 需要做的核心工作 。
Mina 的使用:
//Mina TCP 服务端
package com.mina.test;
import java.util.Date;
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) throws Exception {
System.out.println("服务端与客户端创建连接...");
super.sessionCreated(session);
}
@Override
public void sessionOpened(IoSession session) throws Exception {
System.out.println("服务端与客户端连接打开...");
super.sessionOpened(session);
}
@Override
public void sessionClosed(IoSession session) throws Exception {
System.out.println("服务端与客户端连接关闭...");
super.sessionClosed(session);
}
@Override
public void messageSent(IoSession session, Object message) throws Exception {
System.out.println("服务端发送信息成功..."+message.toString());
super.messageSent(session, message);
}
public void exceptionCaught(IoSession session, Throwable cause)
throws Exception {
System.out.println("服务端发送异常..."+cause.getMessage());
cause.printStackTrace();
}
public void messageReceived(IoSession session, Object message)
throws Exception {
String strMsg = message.toString();
System.out.println("服务端接收到的数据为: "+strMsg);
if (strMsg.trim().equalsIgnoreCase("quit")) {
session.close();
return;
}
Date date = new Date();
session.write(date.toString());
}
public void sessionIdle(IoSession session, IdleStatus status)
throws Exception {
System.out.println("服务端进入空闲状态... " + session.getIdleCount(status));
}
}
package com.mina.test;
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 {
//监听即将到来的TCP连接,建立监控器
IoAcceptor acceptor = new NioSocketAcceptor();
//设置拦截器
acceptor.getFilterChain().addLast("logger", new LoggingFilter());
acceptor.getFilterChain().addLast(
"codec",
new ProtocolCodecFilter(new TextLineCodecFactory(Charset
.forName("GBK"))));
//设置处理类
acceptor.setHandler(new TimeServerHandler());
//设置配置
acceptor.getSessionConfig().setReadBufferSize(2048);
acceptor.getSessionConfig().setIdleTime(IdleStatus.BOTH_IDLE, 10);
//绑定的监听端口,可多次绑定,也可同时绑定多个。
acceptor.bind(new InetSocketAddress(PORT));
System.out.println("服务端启动成功......端口号为: "+PORT);
}
}
//Mina TCP客户端
package com.mina.test;
import org.apache.mina.core.buffer.IoBuffer;
import org.apache.mina.core.service.IoHandlerAdapter;
import org.apache.mina.core.session.IdleStatus;
import org.apache.mina.core.session.IoSession;
import org.apache.mina.proxy.utils.ByteUtilities;
public class TimeClientHandler extends IoHandlerAdapter {
@Override
public void messageReceived(IoSession iosession, Object message)
throws Exception {
IoBuffer bbuf = (IoBuffer) message;
byte[] byten = new byte[bbuf.limit()];
bbuf.get(byten, bbuf.position(), bbuf.limit());
System.out.println("客户端收到消息" + ByteUtilities.asHex(byten));
}
@Override
public void exceptionCaught(IoSession session, Throwable cause)
throws Exception {
System.out.println("客户端异常");
super.exceptionCaught(session, cause);
}
@Override
public void messageSent(IoSession iosession, Object obj) throws Exception {
System.out.println("客户端消息发送");
super.messageSent(iosession, obj);
}
@Override
public void sessionClosed(IoSession iosession) throws Exception {
System.out.println("客户端会话关闭");
super.sessionClosed(iosession);
}
@Override
public void sessionCreated(IoSession iosession) throws Exception {
System.out.println("客户端会话创建");
super.sessionCreated(iosession);
}
@Override
public void sessionIdle(IoSession iosession, IdleStatus idlestatus)
throws Exception {
System.out.println("客户端会话休眠");
super.sessionIdle(iosession, idlestatus);
}
@Override
public void sessionOpened(IoSession iosession) throws Exception {
System.out.println("客户端会话打开");
super.sessionOpened(iosession);
}
}
package com.mina.test;
import java.net.InetSocketAddress;
import org.apache.mina.core.buffer.IoBuffer;
import org.apache.mina.core.future.ConnectFuture;
import org.apache.mina.core.service.IoConnector;
import org.apache.mina.core.session.IoSession;
import org.apache.mina.transport.socket.nio.NioSocketConnector;
public class MinaTimeClient {
private static final int PORT = 6488;
private static IoConnector connector;
private static IoSession session;
public static void main(String[] args) throws Exception {
TimeClientHandler clientHandler=new TimeClientHandler();
connector = new NioSocketConnector();
//设置处理类
connector.setHandler(clientHandler);
ConnectFuture connFuture = connector.connect(new InetSocketAddress("localhost", PORT));
connFuture.awaitUninterruptibly();
session = connFuture.getSession();
clientHandler.sessionOpened(session);
System.out.println("TCP 客户端启动");
for(int j=0;j<5;j++){ // 发送两遍
byte[] bts = new byte[20];
for (int i = 0; i < 20; i++) {
bts[i] = (byte) i;
}
IoBuffer buffer = IoBuffer.allocate(20);
// 自动扩容
buffer.setAutoExpand(true);
// 自动收缩
buffer.setAutoShrink(true);
buffer.put(bts);
buffer.flip();
session.write(buffer);
Thread.sleep(2000);
}
// 关闭会话,待所有线程处理结束后
connector.dispose(true);
}
}
mina 实例(转载)的更多相关文章
- java-通讯stocket插件mina实例
mina是对nio的具体实现.是目前比较高效和流行的nio(非阻塞式I/O)框架 mina主要包括: 其中服务端为:NioSocketAcceptor 客户端为:NioSocketConnector ...
- Python验证码识别处理实例(转载)
版权声明:本文为博主林炳文Evankaka原创文章,转载请注明出处http://blog.csdn.net/evankaka 一.准备工作与代码实例 1.PIL.pytesser.tesseract ...
- Java WebService 简单实例[转载]
[注意,本文转载自 http://hyan.iteye.com/ ] 一.准备工作(以下为本实例使用工具) 1.MyEclipse10.7.1 2.JDK 1.6.0_22 二.创建服务端 1 ...
- linux shell 流程控制(条件if,循环【for,while】,选择【case】语句实例 --转载
http://www.cnblogs.com/chengmo/archive/2010/10/14/1851434.html nux shell有一套自己的流程控制语句,其中包括条件语句(if),循环 ...
- vsftpd虚拟用户创建实例(转载)
vsftpd虚拟用户创建实例 发布:theboy 来源:net [大 中 小] vsftpd虚拟用户创建实例,有需要的朋友可以参考下. vsftpd虚拟用户创建实例,有需要的朋友可以参考 ...
- Java元组Tuple使用实例--转载
原文地址:http://50vip.com/35.html 一.为什么使用元组tuple? 元组和列表list一样,都可能用于数据存储,包含多个数据:但是和列表不同的是:列表只能存储相同的数据类型,而 ...
- Dubbo入门实例--转载
原文地址:http://blog.csdn.net/ruishenh/article/details/23180707?utm_source=tuicool 1. 概述 Dubbo是一个分布式服务 ...
- 分享php中四种webservice实现的简单架构方法及实例[转载]
[转载]http://www.itokit.com/2012/0417/73615.html 本人所了解的webservice有以下几种:PHP本身的SOAP,开源的NUSOAP,商业版的PHPRPC ...
- Java Socket 通信实例 - 转载
基于Tcp协议的简单Socket通信实例(JAVA) 好久没写博客了,前段时间忙于做项目,耽误了些时间,今天开始继续写起~ 今天来讲下关于Socket通信的简单应用,关于什么是Socket以及一些 ...
随机推荐
- Girl_iOS100天学iOS的第一天(规划)
不好的开端. 只是还好,总算是開始. 今天一直在做项目中的某个模块,发现自己尽管工作了一段时间,但编码速度还是够慢的 >.< 探究其为什么慢的原因,还是由于自己对某些控件等基础的不熟悉,如 ...
- Java面试题之Class.forName的作用
按参数中指定的字符串形式的类名去搜索并加载相应的类,如果该类字节码已经被加载过,则返回代表该字节码的Class实例对象,否则,按类加载器的委托机制去搜索和加载该类,如果所有的类加载器都无法加载到该类, ...
- php什么是变量的数据类型
什么是变量的数据类型 在变量中,由于变量占用的空间单元不一样(占的地盘大小不一样),也分成几种数据类型,就像超市商品的包装袋,有几种不同类型,不同的商品使用不同的包装袋.我们可以通过使用“memory ...
- CSS或者JS实现鼠标悬停显示另一元素
想达到鼠标悬停到元素a上,显示另一个元素b,可以通过css实现也可以通过js实现.js:写两个函数:mouseenter,mouseleave,例如:其中 $("#a").mous ...
- C#根据汉字生成拼音首字母全称
static void Main(string[] args) { string s = GetChineseSpell("周杰伦"); Console.WriteLine(s.T ...
- Eclipse下运行拷贝的项目,更改项目名后报404
右键项目->Properties->Web Project Settings 将“Context root”改为你的项目名称
- OCP准备记录
0628: 051 OK053 1-192! 加油了,每天至少100道吧明天复习一下626,627,628这几天的成果先看一遍对的,再看一遍错的!!最少要把051复习一遍 0629: 今天忙了太久 只 ...
- How to Send an Email Using UTL_SMTP with Authenticated Mail Server. (文档 ID 885522.1)
APPLIES TO: PL/SQL - Version 9.2.0.1 to 12.1.0.1 [Release 9.2 to 12.1]Information in this document a ...
- 第一次线上OJ水友赛
偶然的机会遇到了这个神奇的网站http://www.luogu.org/ 巧遇今天又有小比赛果断去试试,为我的蓝桥北京之旅练练手. 苦苦的在机房刷了一下午,大概做到了6点半. 最激动的是等成绩了, ...
- 一致性哈希(Consistent Hashing)
前言:对于一致性哈希已经不是罕见概念,在此只是对原有理论概念的一个整理和用自己的理解讲述,希望对新手有些许帮助,利人利己足矣. 1.概念 一致哈希是一种特殊的哈希算法.在使用一致哈希算法后,哈希表槽位 ...