使用ProtocolCodecFilter解决以下问题
1、TCP 担保以正确的顺序交付所有数据包。但是没有担保对于在发送端写操作时影响到接收端的读事件。在 MINA 术语中:如果没有 ProtocolCodecFilter 的话,一个由发送端对 IoSession.write(Object message) 的调用将导致多个接收端的 messageReceived(IoSession session, Object message) 事件,多个 IoSession.write(Object message) 的调用只会引起唯一的一个 messageReceived 事件。当你的客户端和服务器端运行在同一台主机上 (或者处于同一个本地网) 而你的应用能够应对这种情况时,你可能不会遭遇到这种情况。
2、大多数网络应用需要一种方法以找出当前消息的结束位置和下一条消息的起始位置。
3、你完全可以在你的 IoHandler 实现所有的这些逻辑,但是添加一个 ProtocolCodecFilter 可以让你的代码更加清晰并容易维护。
4、它将你的协议逻辑从你的业务逻辑中 (IoHandler) 剥离开来。
ProtocolCodecFilter在Filter Chain中的位置:
如何使用ProtocolCodecFilter:
你的应用接收到的基本上是一串字节,你需要将这些字节转换为消息 (高层对象)。 有三种常见的技术用来将字节流分割为消息:
1、使用固定长度的字节
2、使用固定长度的报头来指示出报体的长度
3、使用定界符。
这里使用第二种和第三种方式,第二种使用固定长度的报头来指示出报体的长度,定义协议的格式为:
协议格式:协议总字节数,协议压缩后的长度,协议压缩前的长度,协议内容(压缩,将对象存为协议的内容)
final ClientServerMessage clientMsg = new ClientServerMessage(); clientMsg.setMsgId(messageId); clientMsg.setContent(content); content = JsonUtils.toJSONString(clientMsg); byte[] beforeZip = content.getBytes(); final int capacity = beforeZip.length + 12; final ByteBuffer buffer = ByteBuffer.allocate(capacity); buffer.putInt(capacity); buffer.putInt(beforeZip.length); buffer.putInt(beforeZip.length); buffer.put(beforeZip); buffer.flip();
在acceptor的Filter链中加入过滤器
acceptor.getFilterChain().addLast("logger", new LoggingFilter()); acceptor.getFilterChain().addLast("codec", new ProtocolCodecFilter(new ObjectSerializationCodecFactory())));
acceptor.getFilterChain().addLast("logger", new LoggingFilter()); //设定这个过滤器将一行一行(/r/n)的读取数据 acceptor.getFilterChain().addLast("codec", new ProtocolCodecFilter(new TextLineCodecFactory()));