为什么使用协议解码过滤器 ProtocolCodecFilter ?
1) TCP保证所有的包以正确是顺序传递,但不保证发送方的一次写操作在接收方产生一次读操作。在 MINA 的术语中:没有 ProtocolCodecFilter ,发送方的一次 IoSession.write(Object message) 导致接收方多次 messageReceived(IoSession session, Object message) 事件,多次调用 IoSession.write(Object message) 可以导致单一的 messageReceived 事件。当服务器和客户端在同一台主机(或同一局域网)时,你可能不会遇到这种行为。但你的应用程序可能会遇到。
2) 大多数应用程序需要一种方法来找出当前消息的结束位置和下一个消息的开始位置。
你可以在IoHandler 里实现这些逻辑,但添加一个 ProtocolCodecFilter 可以使你的代码更加清晰和易于维护。它允许你分离协议逻辑和业务逻辑( IoHandler )。
应用程序基本上是接收一串字节,需要转换这些字节到消息(高层对象)。
有三种常用的技术来分割字节流到消息:
1、使用定长消息
2、使用固定长度的头来指示内容体长度
3、使用分隔符。
这里使用分割符(换行)来编写时间服务器的解码器。
时间服务器的请求对象为java.lang.String,对应的协议解码器为:
org.apache.mina.filter.codec.textline.TextLineEncoder和org.apache.mina.filter.codec.textline.TextLineDecoder。
响应对象定义如下:
public class TimeResponse {
private String client; // 客户端发送到字符串
private Date date;
public TimeResponse(String client, Date date) {
this.client = client;
this.date = date;
}
public String getClient() {
return client;
}
public Date getDate() {
return date;
}
}
下面是响应的编码器:
public class TimeResponseEncoder extends ProtocolEncoderAdapter {
@Override
public void encode(IoSession session, Object message,
ProtocolEncoderOutput out) throws Exception {
TimeResponse res = (TimeResponse) message;
IoBuffer buff = IoBuffer.allocate(32);
buff.setAutoExpand(true);
buff.setAutoShrink(true);
CharsetEncoder encoder = Charset.forName("UTF-8").newEncoder();
buff.putString(res.getClient() + " 您好!服务器时间是:", encoder);
Date date = res.getDate();
SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd,HH时mm分ss秒");
buff.putString(sdf.format(date), encoder);
buff.put((byte)'\n');
buff.flip();
out.write(buff);
out.flush();
System.err.println("res encode end .... ");
}
}
业务处理器通过IoSession.write()写出的都是响应对象,所以这里可以直接进行强类型转换
TimeResponse res = (TimeResponse) message;
编码后的内容是写到 ProtocolEncoderOutput out,传给下一个过滤器。
然后是响应的解码器:
public class TimeResponseDecoder extends CumulativeProtocolDecoder {
@Override
protected boolean doDecode(IoSession session, IoBuffer in,
ProtocolDecoderOutput out) throws Exception {
CharsetDecoder decoder = Charset.forName("UTF-8").newDecoder();
int start = in.position();
int end = in.remaining() - 1;
if (end >= 0 && in.get(end) == (byte) '\n') {
String res = in.getString(decoder);
out.write(res);
return true;
} else {
in.position(start);
}
return false;
}
}
解码器继承自CumulativeProtocolDecoder的好处是,当缓存的内容还不够解码为一个响应对象时,可以继续缓存响应内容,只要返回false即可。
有了请求和响应的编解码器后,定义一个解码器工厂:
public class TimeResponseCodecFactory implements ProtocolCodecFactory {
private ProtocolDecoder decoder;
private ProtocolEncoder encoder;
public TimeResponseCodecFactory(boolean server) {
if(server) {
decoder = new TextLineDecoder(Charset.forName("UTF-8"));
encoder = new TimeResponseEncoder();
} else {
decoder = new TimeResponseDecoder();
encoder = new TextLineEncoder(Charset.forName("UTF-8"));
}
}
@Override
public ProtocolDecoder getDecoder(IoSession session) throws Exception {
return decoder;
}
@Override
public ProtocolEncoder getEncoder(IoSession session) throws Exception {
return encoder;
}
}
MINA会调用工厂的 getDecoder 和 getEncoder 方法。
注意:服务器端的解码器是请求解码器,编码器是响应编码器;客户端的解码器是响应解码器,编码器是请求编码器。
修改服务器和客户端的过滤器配置
connector.getFilterChain().addLast("codec", new ProtocolCodecFilter(new TimeResponseCodecFactory(true/false)));
服务器端的处理器现在可以直接写响应对象了:
public class TimeServerHandler extends IoHandlerAdapter {
private Logger log = LoggerFactory.getLogger(TimeServerHandler.class);
@Override
public void messageReceived(IoSession session, Object message)
throws Exception {
String str = message.toString();
log.info("server receive :" + str);
if("quit".equalsIgnoreCase(str.trim())) {
session.close(true);
return;
}
Date date = new Date();
TimeResponse res = new TimeResponse(str, date);
session.write(res);
log.info("message writter ...");
}
}
而客户端的处理器也可以直接处理响应对象:
public class ClientHandler extends IoHandlerAdapter {
@Override
public void messageReceived(IoSession session, Object message)
throws Exception {
String msg = (String) message;
System.out.println("response :" + msg);
}
}
有了协议解码过滤器,处理器就不需要考虑底层的编解码的问题,只需要处理高层的业务对象,达到了分层的目的。
转自:http://wen866595.iteye.com/blog/1154137
相关推荐
MINA(Java Multicast Network Application Framework)是Apache软件基金会开发的一个网络应用...同时,结合提供的博客链接(虽然在这里没有具体内容),你还可以找到更多关于MINA协议解码过滤器使用的示例和实践技巧。
在Java的网络编程中,...理解Mina的过滤器机制和编码解码器接口,能够帮助开发者高效地处理网络通信中的数据转换,从而实现复杂的应用场景。通过不断地实践和优化,你可以构建出符合业务需求的高效、可靠的网络服务。
1. **Filter Chain**:Mina的核心设计模式之一是过滤器链。每个连接都有一系列过滤器,它们按照顺序处理入站和出站事件。过滤器可以实现特定功能,如数据编码解码、安全验证、性能监控等。 2. **Session**:Session...
开发者可以定义多个过滤器,每个过滤器可以执行特定的操作,如数据编码、解码或安全检查。过滤器链的概念使得我们可以按顺序处理数据,增强了代码的可扩展性。 3. **ProtocolHandler**:协议处理器是处理特定协议的...
6. **丰富的API**:MINA提供了一套完整的API,包括Filter(过滤器)机制,可以方便地对网络数据流进行拦截、修改或增强。 7. **自定义编码与解码**:如前所述,MINA支持自定义编解码器,允许开发者根据业务需求定制...
2. 在解码过滤器中,数据被分割成多个“消息”单元,每个消息对应一个连接。 3. 消息被传递给相应的解码器进行解码,解码器根据协议解析出有意义的信息。 4. 解码后的对象被传递到下一个过滤器,直至到达业务处理...
2. **Filter Chain**:MINA的过滤器链机制,允许开发者插入自定义的过滤器来处理进/出站数据,实现数据预处理、安全检查等功能。 3. **Transport Layer**:MINA提供了多种传输层实现,如NioSocketAcceptor和...
4. **过滤器链**:MINA引入了过滤器的概念,数据在传输过程中会经过一系列过滤器,每个过滤器可以执行特定的操作,如编码、解码、日志记录等。这种设计使得模块化和复用变得简单。 5. **多线程支持**:MINA支持多...
过滤器可以用于数据编码解码、身份验证、压缩和日志记录等任务,增强了模块化和灵活性。 4. **协议独立性**:MINA不绑定到特定的网络协议,因此可以轻松支持TCP、UDP以及其他自定义协议。这使得MINA成为构建多种...
使用MINA文档说明书,你可以学习如何配置MINA项目,创建服务端和客户端,设置过滤器,编写编码解码器,以及处理各种网络事件。文档还可能包含详细的API参考,示例代码,以及常见问题解答,以帮助开发者快速上手并...
1. **Filter机制**:MINA的过滤器机制类似于Servlet中的Filter,它允许我们对进出的数据进行拦截、修改或转发。通过自定义过滤器,我们可以实现HTTP协议的解析、编码等功能。 2. **Handler处理**:MINA的处理器是...
3. **过滤器链**:Mina的过滤器链机制使得开发者可以方便地添加、删除和调整数据处理流程,增加了代码的可复用性和可扩展性。 4. **协议编解码**:Mina提供了多种编码解码工厂,如LineDelimiter codec用于按行分割...
- **添加编码器和解码器**:通过`FilterChainBuilder`创建过滤器链,添加自定义的编码器和解码器,确保数据在发送和接收时正确处理。 3. **创建Mina客户端** - **配置Connector**:使用`TcpClient`或`...
2. **Filter Chain机制**:MINA采用了过滤器链的设计模式,允许开发者通过添加、删除或修改过滤器来实现特定的功能,如数据编码解码、安全性处理、性能监控等。过滤器链使得代码结构清晰,易于扩展和维护。 3. **...
2. **Filter Chain**:MINA采用过滤器链模式来处理网络通信。每个过滤器都可以执行特定的处理任务,如数据编码解码、安全性检查等。过滤器之间通过IoHandler接口交互,形成一个可扩展的处理流程。 3. **Transport ...
7. **minaDemo项目结构**:压缩包中的minaDemo项目可能包含以下组件:主类(启动服务)、配置文件(如XML配置服务)、过滤器实现、编码解码器、以及IoHandler的实现。通过分析这个Demo,我们可以了解到如何实际搭建...
5. **强大的过滤器架构**:允许开发者通过组合过滤器实现复杂的功能,如数据编码解码、身份验证、流量控制等。 MINA广泛应用于各种网络应用,如聊天服务器、游戏服务器、远程桌面服务、FTP服务器等。对于开发人员来...
2. **过滤器链机制**:MINA采用了过滤器链的设计模式,允许开发者通过添加、删除或调整过滤器来处理网络通信的各种需求,如数据编码解码、身份验证、压缩等。 3. **协议无关性**:MINA不局限于特定的网络协议,它...
每个过滤器都可以在数据传输过程中进行拦截和处理,如数据编码、解码、安全检查等。过滤器之间通过`Filter.nextFilter`方法串联,形成一个执行序列。开发者可以根据需求插入自定义过滤器,实现对输入和输出数据的...
- **过滤器链**:MINA的过滤器链设计,使得开发者可以通过添加、删除或替换过滤器来实现复杂的数据处理逻辑,增强了代码复用性和可维护性。 - **多协议支持**:MINA支持多种网络协议,开发者可以根据需求选择合适...