Apache MINA学习之路(2)
1.IoService 接口作用:IoService 是创建服务的顶层接口,无论客户端还是服务端,都是从它继承实现的。
常用接口为:IoService,IoAcceptor ,IoConnector
常用类为:NioSocketAcceptor ,NioSocketConnector
2.IoFilter 接口 -- 过滤器
官方文档中的作用:
(1)记录事件的日志(Mina默认提供了LoggingFilter)
(2)测量系统性能
(3)信息验证
(4)过载控制
(5)信息的转换(主要就是编码和解码)
(6)和其他更多的信息
常用接口为:IoFilter ,IoFilterChainBuilder
常用类为:IoFilterAdapter,DefaultIoFilterChainBuilder,ProtocolCodecFilter,LoggingFilter
注:Mina 中有一个重要的设计模式-责任链模式
资料阅读:http://www.iteye.com/topic/1124504
自定义编解码器
编码和解码的前提就是协议的制定:比如使用 Mina 自带的根据文本换行符解码的 TextLineCodecFactory(), 如果遇到文本换行符就开始编解码!
制定协议的方法:
●定长消息法
●字符定界法
● 定长报文头
根据协议, 把二进制数据转换成 Java 对象称为解码 (也叫做拆包);把 Java对象转换为二进制数据称为编码(也叫做打包)。
模拟根据文本换行符编解码
解码器
import java.nio.charset.Charset;
import org.apache.mina.core.buffer.IoBuffer;
import org.apache.mina.core.session.IoSession;
import org.apache.mina.filter.codec.ProtocolDecoder;
import org.apache.mina.filter.codec.ProtocolDecoderOutput;
public class MyCodecDecoder implements ProtocolDecoder {
private Charset charset = Charset.forName("UTF-8");
//allocate(int capacity,boolean useDirectBuffer)第一个参数指定初始化容量,第二个参数指定使用直接缓冲区还是 JAVA 内存堆的缓存区,默认为 false
//setAutoExpand自动扩展容量
IoBuffer buf = IoBuffer.allocate(100).setAutoExpand(true);
public void decode(IoSession session, IoBuffer in, ProtocolDecoderOutput out)
throws Exception {
//判断当前是否有数据
while (in.hasRemaining()) {
byte b = in.get();
buf.put(b);
if (b == '\n') {
//为了读取做好准备,一般是结束buf操作,将buf写入输出流时调用
buf.flip();
byte[] msg = new byte;
buf.get(msg);
String message = new String(msg, charset);
// 解码成功,把buf重置
buf = IoBuffer.allocate(100).setAutoExpand(true);
out.write(message);
}
}
}
public void dispose(IoSession session) throws Exception {
}
public void finishDecode(IoSession session, ProtocolDecoderOutput out)
throws Exception {
}
}
编码器
import java.nio.charset.Charset;
import java.nio.charset.CharsetEncoder;
import org.apache.mina.core.buffer.IoBuffer;
import org.apache.mina.core.session.IoSession;
import org.apache.mina.filter.codec.ProtocolEncoder;
import org.apache.mina.filter.codec.ProtocolEncoderOutput;
public class MyCodecEncoder implements ProtocolEncoder {
private Charset charset = Charset.forName("UTF-8");
public void encode(IoSession session, Object message,
ProtocolEncoderOutput out) throws Exception {
IoBuffer buf = IoBuffer.allocate(100).setAutoExpand(true);
CharsetEncoder ce = charset.newEncoder();
buf.putString(message.toString(), ce);
// buf.put(message.toString().getBytes(charset));
//在结尾添加\r\n输出
buf.put((byte) '\r');
buf.put((byte) '\n');
buf.flip();
out.write(buf);
}
public void dispose(IoSession session) throws Exception {
}
}
编解码器工厂类
import org.apache.mina.core.session.IoSession;
import org.apache.mina.filter.codec.ProtocolCodecFactory;
import org.apache.mina.filter.codec.ProtocolDecoder;
import org.apache.mina.filter.codec.ProtocolEncoder;
public class MyCodecFactory implements ProtocolCodecFactory {
public ProtocolDecoder getDecoder(IoSession session) throws Exception {
return new MyCodecDecoder();
}
public ProtocolEncoder getEncoder(IoSession session) throws Exception {
return new MyCodecEncoder();
}
}
测试
// 设置过滤器(使用Mina提供的文本换行符编解码器)
acceptor.getFilterChain().addLast(
"codec",
new ProtocolCodecFilter(new MyTextLineCodecFactory()));
启动服务器,通过telnet进行测试
3.IoHandler 接口 --业务处理
常用类为:IoHandlerAdapter
IoHandler 是 Mina 实现其业务逻辑的接口;在 IoHandler 中定义了 7个方法,根据 I/O 事件来触发对应的方法:
import org.apache.mina.core.session.IdleStatus;
import org.apache.mina.core.session.IoSession;
public interface IoHandler {
// 当一个新的连接建立时,由 I/O processor thread 调用
void sessionCreated(IoSession session) throws Exception;
// 当连接打开是调用
void sessionOpened(IoSession session) throws Exception;
// 当连接关闭时调用
void sessionClosed(IoSession session) throws Exception;
// 当连接进入空闲状态时调用
void sessionIdle(IoSession session, IdleStatus status) throws Exception;
// 当实现 IoHandler 的类抛出异常时调用
void exceptionCaught(IoSession session, Throwable cause) throws Exception;
// 当接收了一个消息时调用
void messageReceived(IoSession session, Object message) throws Exception;
// 当一个消息被(IoSession.write)发送出去后调用
void messageSent(IoSession session, Object message) throws Exception;
}
页:
[1]