minalo解码器相关问题

【APACHE MINA2.0开发之二】自定义实现SERVER/CLIENT端的编解码工厂(自定义编码与解码器)!
【APACHE MINA2.0开发之二】自定义实现SERVER/CLIENT端的编解码工厂(自定义编码与解码器)!
本站文章均为 李华明Himi 原创,转载务必在明显处注明:
转载自【黑米GameDev街区】 原文链接: http://www.himigame.com/apache-mina/839.html
在上一篇博文中已经简单介绍过“过滤器”的概念,那么在Mina 中的协议编解码器通过过滤器 ProtocolCodecFilter 构造,这个过滤器的构造方法需 要一个 ProtocolCodecFactory,这从前面注册 TextLineCodecFactory 的代码就可以看出来。
本站文章均为
原创,转载务必在明显处注明:
转载自【黑米GameDev街区】 原文链接:
在上一篇博文中已经简单介绍过“过滤器”的概念,那么在Mina 中的协议编解码器通过过滤器 ProtocolCodecFilter 构造,这个过滤器的构造方法需 要一个 ProtocolCodecFactory,这从前面注册 TextLineCodecFactory 的代码就可以看出来。 ProtocolCodecFactory 中有如下两个方法:
public interface ProtocolCodecFactory {
ProtocolEncoder getEncoder(IoSession session) throws E
ProtocolDecoder getDecoder(IoSession session) throws E
因此,构建一个 ProtocolCodecFactory 需要 ProtocolEncoder、ProtocolDecoder 两个实例。你可能要问 JAVA 对象和二进制数据之间如何转换呢?这个要依据具体的通信协议,也就是 Server 端要和 Client 端约定网络传输的数据是什么样的格式,譬如:第一个字节表示数据 长度,第二个字节是数据类型,后面的就是真正的数据(有可能是文字、有可能是图片等等), 然后你可以依据长度从第三个字节向后读,直到读取到指定第一个字节指定长度的数据。
简单的说,HTTP 协议就是一种浏览器与 Web 服务器之间约定好的通信协议,双方按照指定 的协议编解码数据。我们再直观一点儿说,前面一直使用的 TextLine 编解码器就是在读取 网络上传递过来的数据时,只要发现哪个字节里存放的是 ASCII 的 10、13 字符(\r、\n), 就认为之前的字节就是一个字符串(默认使用 UTF-8 编码)。
以上所说的就是各种协议实际上就是网络七层结构中的应用层协议,它位于网络层(IP)、 传输层(TCP)之上,Mina 的协议编解码器就是让你实现一套自己的应用层协议栈。
首先我们创建一个传递的对象类:
package com.entity;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
import org.hibernate.annotations.Index;
* @author Himi
@Table(name = "playerAccount")
public class PlayerAccount_Entity {
private int id;
private String name;
private String emailAdress;
private int sex;// 0=man 1=woman
@Column(name = "playerAccountID")
@GeneratedValue(strategy = GenerationType.AUTO)
public int getId() {
return id;
public void setId(int id) {
this.id = id;
@Index(name="nameIndex")
public String getName() {
return name;
public void setName(String name) {
this.name = name;
public String getEmailAdress() {
return emailAdress;
public void setEmailAdress(String emailAdress) {
this.emailAdress = emailAdress;
public int getSex() {
return sex;
public void setSex(int sex) {
this.sex = sex;
2. 创建一个编码类:
package com.protocol;
* @author Himi
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.ProtocolEncoderAdapter;
import org.apache.mina.filter.codec.ProtocolEncoderOutput;
import com.entity.PlayerAccount_Entity;
public class HEncoder extends ProtocolEncoderAdapter {
private final Charset charset;
public HEncoder(Charset charset) {
this.charset = charset;
public void encode(IoSession arg0, Object arg1, ProtocolEncoderOutput arg2)
throws Exception {
CharsetEncoder ce = charset.newEncoder();
PlayerAccount_Entity paEntity = (PlayerAccount_Entity) arg1;
String name = paEntity.getName();
IoBuffer buffer = IoBuffer.allocate(100).setAutoExpand(true);
buffer.putString(name, ce);
buffer.flip();
arg2.write(buffer);
在 Mina 中编写编码器可以实现 ProtocolEncoder,其中有 encode()、dispose()两个方法需 要实现。这里的 dispose()方法用于在销毁编码器时释放关联的资源,由于这个方法一般我 们并不关心,所以通常我们直接继承适配器 ProtocolEncoderAdapter。
3.创建一个解码类:
package com.protocol;
* @author Himi
import java.nio.charset.Charset;
import java.nio.charset.CharsetDecoder;
import org.apache.mina.core.buffer.IoBuffer;
import org.apache.mina.core.session.IoSession;
import org.apache.mina.filter.codec.CumulativeProtocolDecoder;
import org.apache.mina.filter.codec.ProtocolDecoderOutput;
import com.entity.PlayerAccount_Entity;
public class HDecoder extends CumulativeProtocolDecoder {
private final Charset charset;
public HDecoder(Charset charset) {
this.charset = charset;
protected boolean doDecode(IoSession arg0, IoBuffer arg1,
ProtocolDecoderOutput arg2) throws Exception {
CharsetDecoder cd = charset.newDecoder();
String name = arg1.getString(cd);
PlayerAccount_Entity paEntity = new PlayerAccount_Entity();
paEntity.setName(name);
arg2.write(paEntity);
return true;
在 Mina 中编写解码器,可以实现 ProtocolDecoder 接口,其中有 decode()、finishDecode()、 dispose()三个方法。这里的 finishDecode()方法可以用于处理在 IoSession 关闭时剩余的 读取数据,一般这个方法并不会被使用到,除非协议中未定义任何标识数据什么时候截止 的约定,譬如:Http 响应的 Content-Length 未设定,那么在你认为读取完数据后,关闭 TCP 连接(IoSession 的关闭)后,就可以调用这个方法处理剩余的数据,当然你也可以忽略调 剩余的数据。同样的,一般情况下,我们只需要继承适配器 ProtocolDecoderAdapter,关 注 decode()方法即可。
但前面说过解码器相对编码器来说,最麻烦的是数据发送过来的规模,以聊天室为例,一个 TCP 连接建立之后,那么隔一段时间就会有聊天内容发送过来,也就是 decode()方法会被往 复调用,这样处理起来就会非常麻烦。那么 Mina 中幸好提供了 CumulativeProtocolDecoder 类,从名字上可以看出累积性的协议解码器,也就是说只要有数据发送过来,这个类就会去 读取数据,然后累积到内部的 IoBuffer 缓冲区,但是具体的拆包(把累积到缓冲区的数据 解码为 JAVA 对象)交由子类的 doDecode()方法完成,实际上 CumulativeProtocolDecoder 就是在 decode()反复的调用暴漏给子类实现的 doDecode()方法。
具体执行过程如下所示:
A. 你的 doDecode()方法返回 true 时,CumulativeProtocolDecoder 的 decode()方法会首先判断你是否在 doDecode()方法中从内部的 IoBuffer 缓冲区读取了数据,如果没有,ce); buffer.putString(smsContent, ce);buffer.flip();则会抛出非法的状态异常,也就是你的 doDecode()方法返回 true 就表示你已经消费了 本次数据(相当于聊天室中一个完整的消息已经读取完毕),进一步说,也就是此时你 必须已经消费过内部的 IoBuffer 缓冲区的数据(哪怕是消费了一个字节的数据)。如果 验证过通过,那么 CumulativeProtocolDecoder 会检查缓冲区内是否还有数据未读取, 如果有就继续调用 doDecode()方法,没有就停止对 doDecode()方法的调用,直到有新 的数据被缓冲。
B. 当你的 doDecode()方法返回 false 时,CumulativeProtocolDecoder 会停止对 doDecode() 方法的调用,但此时如果本次数据还有未读取完的,就将含有剩余数据的 IoBuffer 缓 冲区保存到 IoSession 中,以便下一次数据到来时可以从 IoSession 中提取合并。如果 发现本次数据全都读取完毕,则清空 IoBuffer 缓冲区。简而言之,当你认为读取到的数据已经够解码了,那么就返回 true,否则就返回 false。这 个 CumulativeProtocolDecoder 其实最重要的工作就是帮你完成了数据的累积,因为这个工 作是很烦琐的。
4.创建一个编解码工厂类:
package com.protocol;
import java.nio.charset.Charset;
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;
* @author Himi
public class HCoderFactory implements ProtocolCodecFactory {
private final HEncoder encoder;
private final HDecoder decoder;
public HCoderFactory() {
this(Charset.defaultCharset());
public HCoderFactory(Charset charSet) {
this.encoder = new HEncoder(charSet);
this.decoder = new HDecoder(charSet);
public ProtocolDecoder getDecoder(IoSession arg0) throws Exception {
// TODO Auto-generated method stub
return decoder;
public ProtocolEncoder getEncoder(IoSession arg0) throws Exception {
// TODO Auto-generated method stub
return encoder;
这个工厂类就是包装了编码器、解码器,通过接口中的 getEncoder()、getDecoder() 方法向 ProtocolCodecFilter 过滤器返回编解码器实例,以便在过滤器中对数据进行编解码 处理。
5. 以上3个编解码有关的类在Server与Client读需要有,那么同时我们创建好了自定义的编解码有关的类后,我们设置Server和Client的编码工厂为我们自定义的编码工厂类:
DefaultIoFilterChainBuilder chain = acceptor.getFilterChain(); chain.addLast("mycoder", new ProtocolCodecFilter(new HCoderFactory( Charset.forName("UTF-8"))));
6.书写测试的消息处理器类Client和Server端;
Client端消息处理器:
* @author Himi
import org.apache.mina.core.service.IoHandlerAdapter;
import org.apache.mina.core.session.IoSession;
import com.protocol.PlayerAccount_Entity;
public class ClientMainHanlder extends IoHandlerAdapter {
// 当一个客端端连结到服务器后
public void sessionOpened(IoSession session) throws Exception {
PlayerAccount_Entity ho = new PlayerAccount_Entity();
ho.setName("李华明 ");
session.write(ho);
// 当一个客户端关闭时
public void sessionClosed(IoSession session) {
System.out.println("I'm Client &&
I closed!");
// 当服务器端发送的消息到达时:
public void messageReceived(IoSession session, Object message)
throws Exception {
PlayerAccount_Entity ho = (PlayerAccount_Entity) message;
System.out.println("Server Say:name:" + ho.getName());
Server端消息处理器:
* @author Himi
import org.apache.mina.core.service.IoHandlerAdapter;
import org.apache.mina.core.session.IdleStatus;
import org.apache.mina.core.session.IoSession;
import com.entity.PlayerAccount_Entity;
import com.sessionUtilities.HibernateUtil;
public class MainHanlder extends IoHandlerAdapter {
private int count = 0;
// 当一个新客户端连接后触发此方法.
* 这个方法当一个 Session 对象被创建的时候被调用。对于 TCP 连接来说,连接被接受的时候 调用,但要注意此时 TCP
* 连接并未建立,此方法仅代表字面含义,也就是连接的对象 IoSession 被创建完毕的时候,回调这个方法。 对于 UDP
* 来说,当有数据包收到的时候回调这个方法,因为 UDP 是无连接的。
public void sessionCreated(IoSession session) {
System.out.println("新客户端连接");
// 当一个客端端连结进入时 @Override
* 这个方法在连接被打开时调用,它总是在 sessionCreated()方法之后被调用。对于 TCP 来
* 说,它是在连接被建立之后调用,你可以在这里执行一些认证操作、发送数据等。 对于 UDP 来说,这个方法与
* sessionCreated()没什么区别,但是紧跟其后执行。如果你每 隔一段时间,发送一些数据,那么
* sessionCreated()方法只会在第一次调用,但是 sessionOpened()方法每次都会调用。
public void sessionOpened(IoSession session) throws Exception {
System.out.println("第 " + count + " 个 client 登陆!address: : "
+ session.getRemoteAddress());
// 当客户端发送的消息到达时:
* 对于 TCP 来说,连接被关闭时,调用这个方法。 对于 UDP 来说,IoSession 的 close()方法被调用时才会毁掉这个方法。
public void messageReceived(IoSession session, Object message)
throws Exception {
// // 我们己设定了服务器解析消息的规则是一行一行读取,这里就可转为String:
// String s = (String)
// // Write the received data back to remote peer
// System.out.println("收到客户机发来的消息: " + s);
// // 测试将消息回送给客户端 session.write(s+count); count++;
PlayerAccount_Entity ho = (PlayerAccount_Entity) message;
System.out.println("Client Say:" + ho.getName());
ho.setName("Himi
session.write(ho);
// 当信息已经传送给客户端后触发此方法.
* 当发送消息成功时调用这个方法,注意这里的措辞,发送成功之后,也就是说发送消息是不 能用这个方法的。
public void messageSent(IoSession session, Object message) {
System.out.println("信息已经传送给客户端");
// 当一个客户端关闭时
* 对于 TCP 来说,连接被关闭时,调用这个方法。 对于 UDP 来说,IoSession 的 close()方法被调用时才会毁掉这个方法。
public void sessionClosed(IoSession session) {
System.out.println("one Clinet Disconnect !");
// 当连接空闲时触发此方法.
* 这个方法在 IoSession 的通道进入空闲状态时调用,对于 UDP 协议来说,这个方法始终不会 被调用。
public void sessionIdle(IoSession session, IdleStatus status) {
// System.out.println("连接空闲");
// 当接口中其他方法抛出异常未被捕获时触发此方法
* 这个方法在你的程序、Mina 自身出现异常时回调,一般这里是关闭 IoSession。
public void exceptionCaught(IoSession session, Throwable cause) {
System.out.println("其他方法抛出异常");
OK,首先启动Server端,然后运行Client端,观察控制台:
用云栖社区APP,舒服~
【云栖快讯】云栖社区技术交流群汇总,阿里巴巴技术专家及云栖社区专家等你加入互动,老铁,了解一下?&&
文章2301篇
是一款提供了现场可编程门阵列(FPGA)的计算实例,基于阿里云弹性计算框架,用户可以几分钟内...
阿里云移动APP解决方案,助力开发者轻松应对移动app中随时可能出现的用户数量的爆发式增长、...
兼容Jenkins标准,可提供快速可靠的持续集成与持续交付服务。基于容器技术和阿里云基础服务...
为您提供简单高效、处理能力可弹性伸缩的计算服务,帮助您快速构建更稳定、安全的应用,提升运维效...mina TCP连接 如何接收与发送16进制数据包
[问题点数:40分,结帖人y]
本版专家分:90
结帖率 83.33%
CSDN今日推荐
本版专家分:417
本版专家分:434
匿名用户不能发表回复!|
其他相关推荐&nbsp>&nbsp
&nbsp>&nbsp
&nbsp>&nbsp
Mina中使用多个filter解码时问题
摘要:&Mina中使用多个filter,解码的时候总是出现问题,解码顺序似乎一直有问题。看了源码终于找到问题所在。&ProtocolCodecFilter中有一些AttributeKeyprivatefinalAttributeKeyENCODER=newAttributeKey(ProtocolCodecFilter.class,&encoder&);privatefinalAttributeKeyDECODER=newAttributeK
&Mina中使用多个filter,解码的时候总是出现问题,解码顺序似乎一直有问题。看了源码终于找到问题所在。
ProtocolCodecFilter 中 有一些AttributeKey
private final AttributeKey ENCODER = new AttributeKey(ProtocolCodecFilter.class, &encoder&);
private final AttributeKey DECODER = new AttributeKey(ProtocolCodecFilter.class, &decoder&);
private final AttributeKey DECODER_OUT = new AttributeKey(ProtocolCodecFilter.class, &decoderOut&);
private final AttributeKey ENCODER_OUT = new AttributeKey(ProtocolCodecFilter.class, &encoderOut&);
我原本以为 新new出来的AttributeKey,在Iosession的Map中会是不同的key,但是我错了。
&public int hashCode() {
& & & & int h = 17 * 37 + ((name == null) ? 0 : name.hashCode());
AttributeKey 的hashCode方法被重写了,所以hash值都是根据name来的。
这样导致如果多个ProtocolCodecFilter 这些 key所在value被共享了。这样问题来了
看下DECODER_OUT这个key的value:
private static class ProtocolDecoderOutputImpl extends
& & & & & &AbstractProtocolDecoderOutput {
& & & & public ProtocolDecoderOutputImpl() {
& & & & & & &// Do nothing
& & & & public void flush(NextFilter nextFilter, IoSession session) {
& & & & & & &Queue&Object& messageQueue = getMessageQueue(); & & & & &&
& & & & & & while (!messageQueue.isEmpty()) {
& & & & & & & &nextFilter.messageReceived(session, messageQueue.poll());
& & & & & & }
当第一个filter解码器 解码产生一个对象A,放入messageQueue 然后调用
&while (!messageQueue.isEmpty()) {
& & & & & & & &nextFilter.messageReceived(session, messageQueue.poll());
& & & & & & }
第二个filter解码器根据传入的对象A,解码产生对象B,放入messageQueue 。
这个时候问题来了,!messageQueue.isEmpty() 又变true了循环继续,
传入第二个filter解码器的是刚刚自己产生的对象B,这样显然不能再解码一次对象B。
本文出自 “翼博云添” 博客,请务必保留此出处http://maosz1982.blog.51cto.com/688
以上是的内容,更多
的内容,请您使用右上方搜索功能获取相关信息。
若你要投稿、删除文章请联系邮箱:zixun-group@service.aliyun.com,工作人员会在五个工作日内给你回复。
新用户大礼包!
现在注册,免费体验40+云产品,及域名优惠!
云服务器 ECS
可弹性伸缩、安全稳定、简单易用
&40.8元/月起
预测未发生的攻击
&24元/月起
你可能还喜欢
你可能感兴趣
阿里云教程中心为您免费提供
Mina中使用多个filter解码时问题相关信息,包括
的信息,所有Mina中使用多个filter解码时问题相关内容均不代表阿里云的意见!投稿删除文章请联系邮箱:zixun-group@service.aliyun.com,工作人员会在五个工作日内答复
售前咨询热线
支持与服务
资源和社区
关注阿里云
InternationalMina框架断包、粘包问题解决方式
Apache Mina Server 是一个网络通信应用框架,也就是说,它主要是对基于TCP/IP、UDP/IP协议栈的通信框架(当然。也能够提供JAVA 对象的序列化服务、虚拟机管道通信服务等),Mina 能够帮助我们高速开发高性能、高扩展性的网络通信应用,Mina 提供了事件驱动、异步(Mina 的异步IO 默认使用的是JAVA NIO 作为底层支持)操作的编程模型。
在mina中,一般的应用场景用TextLine的Decode和Encode就够用了(TextLine的默认切割符尽管是\r\n,但事实上分隔符是能够自己指定的,如:newTextLineDecoder(charset, decodingDelimiter);)
但默认解码器每次读取缓冲的数据是有限制的,即ReadBufferSize的大小。默认是2048个字节。当数据包比較大时将被分成多次读取。造成断包。尽管能够通过acceptor.getSessionConfig().setReadBufferSize(newsize)这样的方式来添加默认容量,但毕竟不是王道(太大了浪费空间。肯定会减少数据的处理效率)。
所以。当我们接收的数据的大小不是非常固定,且easy偏大的时候,默认的TextLine就不适合了。这时我们在解析之前就须要推断数据包是否完整,这样处理起来就会非常麻烦。那么Mina 中幸好提供了CumulativeProtocolDecoder
类,从名字上能够看出累积性的协议解码器,也就是说仅仅要有数据发送过来。这个类就会去读取数据。然后累积到内部的IoBuffer 缓冲区,可是详细的拆包(把累积到缓冲区的数据解码为JAVA 对象)交由子类的doDecode()方法完毕,实际上CumulativeProtocolDecoder就是在decode()重复的调用暴漏给子类实现的doDecode()方法。
详细运行步骤例如以下所看到的:
A. 你的doDecode()方法返回true 时,CumulativeProtocolDecoder 的decode()方法会首先推断你是否在doDecode()方法中从内部的IoBuffer 缓冲区读取了数据。假设没有,则会抛出非法的状态异常,也就是你的doDecode()方法返回true 就表示你已经消费了本次数据(相当于聊天室中一个完整的消息已经读取完成),进一步说,也就是此时你必须已经消费过内部的IoBuffer 缓冲区的数据(哪怕是消费了一个字节的数据)。假设验证通过,那么CumulativeProtocolDecoder会检查缓冲区内是否还有数据未读取。假设有就继续调用doDecode()方法。没有就停止对doDecode()方法的调用。直到有新的数据被缓冲。
B. 当你的doDecode()方法返回false 时。CumulativeProtocolDecoder 会停止对doDecode()方法的调用。但此时假设本次数据还有未读取完的,就将含有剩余数据的IoBuffer 缓冲区保存到IoSession 中,以便下一次数据到来时能够从IoSession 中提取合并。假设发现本次数据全都读取完成,则清空IoBuffer 缓冲区。
简而言之,当你觉得读取到的数据已经够解码了。那么就返回true,否则就返回false。这个CumulativeProtocolDecoder事实上最重要的工作就是帮你完毕了数据的累积,由于这个工作是非常烦琐的。
一、&&&&实现解码器
CumulativeProtocolDecoder是一个抽象类,必须继承并实现其doDecode方法。用户自己定义协议的拆分就应该写在doDecode方法中,以下的MyDecoder类是一个其子类的实现:
class MyDecoder extends CumulativeProtocolDecoder {
&&& public
static Logger log = Logger.getLogger(MyDecoder.class);
&&& &* 包解码器组件
&&& private PacketComponent
packetComponent;
&&&& * 这种方法的返回值是重点:
&&&& * 1、当内容刚好时,返回false,告知父类接收下一批内容
&&&& * 2、内容不够时须要下一批发过来的内容,此时返回false,这样父类 CumulativeProtocolDecoder
&&&& *&&&会将内容放进IoSession中,等下次来数据后就自己主动拼装再交给本类的doDecode
&&&& * 3、当内容多时,返回true,由于须要再将本批数据进行读取。父类会将剩余的数据再次推送本
&&&& * 类的doDecode
&&& public
boolean doDecode(IoSession session,IoBuffer in,&
&&&&&&&&&&& ProtocolDecoderOutput out) throws Exception {&
&&& log.info(&in.remaining : &+in.remaining());
&&&&&&& if(in.remaining() & 0){//有数据时。读取前8字节推断消息长度&
&&&&&&&&&&& byte [] sizeBytes =
new byte[8];&
&&&&&&&&&&& in.mark();//标记当前位置。以便reset
//由于我的前数据包的长度是保存在第4-8字节中,
&&&&&&&&&&& in.get(sizeBytes,0,8);//读取4字节&
&&&&&&&&&&&&&&&&&&&&&&& //DataTypeChangeHelper是自己写的一个byte[]转int的一个工具类&
&&&&&&&&&&& int size = (int) DataTypeUtil.bytesToInt(sizeBytes,4);
&&&&&&&&&&& log.info(&size : &+size);
&&&&&&&&&&& in.reset();
&&&&&&&&&&& if(size & in.remaining()){//假设消息内容不够,则重置。相当于不读取size&
&&&&&&&&&&&&&&& return
false;//父类接收新数据,以拼凑成完整数据&
&&&&&&&&&&& } else{&
&&&&&&&&&&&&&&& byte[] bytes =
new byte[size];&&
&&&&&&&&&&&&&&& in.get(bytes, 0, size);
&&&&&&&&&&&&& //把字节转换为Java对象的工具类
&&&&&&&&&&&&&&& PackageData pack =
packetComponent.getDataFromBuffer(IoBuffer.wrap(bytes));
&&&&&&&&&&&&&&& out.write(pack);
&&&&&&&&&&&&&&& if(in.remaining() & 0){//假设读取内容后还粘了包,就让父类再重读&
一次。进行下一次解析&
&&&&&&&&&&&&&&&&&&& return
&&&&&&&&&&&&&&& }&
&&&&&&&&&&& }&
&&&&&&& }&
&&&&&&& return
false;//处理成功,让父类进行接收下个包&
&&& getter();
&&& Setter();
二、&&&&实现编解码工厂和解码器
我们还须要一个编解码工厂,用来为编解码过滤器提供编码器和解码器,解码器此处我们用不到。可是也必须提供,所以能够提供一个空的实现。
&* 编解码工厂
class MyCodecFcatory implements ProtocolCodecFactory {
&&& private ProtocolEncoder
encoder = null;
&&& private ProtocolDecoder
decoder = null;
&&& public MyCodecFcatory(ProtocolEncoder encoder, ProtocolDecoderdecoder) {
&&&&&& this.encoder =
&&&&&& this.decoder =
&&& @Override
&&& public ProtocolEncoder getEncoder(IoSession session)
throws Exception {
&&&&&& return
this.encoder;
&&& @Override
&&& public ProtocolDecoder getDecoder(IoSession session)
throws Exception {
&&&&&& return
this.decoder;
&* 编码器:不做不论什么操作,数据已是约定好的格式。按原格式编码
class MyEncoder extends ProtocolEncoderAdapter {
&&& @Override
&&& public
void encode(IoSession session, Object message,
&&&&&&&&&& ProtocolEncoderOutput out) throws Exception {
&&&&&& // TODO Do nothing
三、&&&&配置编解码过滤器
以下就能够配置编解码过滤器了:
&!-- 累加数据包解码器:解断丢包、粘包问题 --&
id=&codec&
class=&org.apache.mina.filter.codec.ProtocolCodecFilter&&
&&&&&& &constructor-arg&
&&&&&&&&&& &bean
class=&com.mina.codec.MyCodecFcatory&&
&&&&&&&&&&&&& &constructor-arg
index=&0&&
&&&&&&&&&&&&&&&&& &bean
class=&com.mina.codec.MyEncoder&&&/bean&
&&&&&&&&&&&&& &/constructor-arg&
&&&&&&&&&&&&& &constructor-arg
index=&1&&
&&&&&&&&&&&&&&&&& &bean
class=&com.mina.codec.MyDecoder&&
&&&&&&&&&&&&&&&&&&&& &property
name=&packetComponent&&
&&&&&&&&&&&&&&&&&&&&&&&& &bean
class=&com. mina.component.RootComponent&&
&&&&&&&&&&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&&&&&&&&&& &/bean&
&&&&&&&&&&&&&&&&& &&& &/property&
&&&&&&&&&&&&&&&&& &/bean&
&&&&&&&&&&&&& &/constructor-arg&
&&&&&&&&&&&&&&&&&
&&&&&&&&&& &/bean&
&&&&&& &/constructor-arg&
&&& &/bean&
id=&filterChainBuilder&
class=&org.apache.mina.core.filterchain.DefaultIoFilterChainBuilder&&&
&&& & &property
name=&filters&&&
&&& &&& &map&
&&& &&&&& &entry
key=&codec&
value-ref=&codec&/&
&&& &&&&& &entry
key=&logger&
value-ref=&loggerFilter&/&
&&& &&&&& &entry
key=&executors&
value-ref=&executors&/&
&&& &&& &/map&&
&&& & &/property&&
&&& &/bean&&
须要注意的是:在doDecode中通过out.write(pack) 把数据输出后,官方的说明文档中说接下来会继续运行后面的过滤器,然后是IoHandle。假设你是仅仅用了一个编解码过滤器的话,这可能全然没问题,可是假设使用了两个编解码过滤器(可能非常少有人会这样做,但本人因为前期使用了另外一个自己定义的编解码过滤器。后来想加上这个可累加的解码器。为了图省事就在原过滤器的前面新添加了一个编解码过滤器,后来数据流就不走我原来的编解码过滤器了,out.write()之后直接到了IoHandle里面,搞了我好久,无奈最后把两个编解码过滤器合二为一啦。当中原因我还没时间去搞个清楚。为防止大家和我犯同一个错误,特此提醒!)
阅读(...) 评论()

我要回帖

更多关于 minali口红 的文章

 

随机推荐