使用过mina的同学应该都遇到到过,在解码时少包、多包的问题,查阅了很多资料还是迷迷糊糊的,经过
不懈努力,终于解决了。原来解决方法是那样的简单。废话少说,请看列子。
问题:我发送的是xml字符串数据,在发送数据后,接收方在解码的时候可能接到1条,也可能是多条,还
可能是半条或一条半,解决方法就是使用CumulativeProtocolDecoder
首先,在编码的时候要把前4位设成标志位,标志消息内容的长度。里面的重点是doDecode的返回值,一
定要继承CumulativeProtocolDecoder 哦。
清看decode的写法:
public class AsResponseDecoder extends CumulativeProtocolDecoder {
private static Logger LOG = LoggerFactory.getLogger(AsResponseDecoder.class);
private final Charset charset;
public AsResponseDecoder(Charset charset){
this.charset = charset;
}
public boolean doDecode(IoSession session, IoBuffer in,
ProtocolDecoderOutput out) throwsException {
CharsetDecoder cd = charset.newDecoder();
if(in.remaining() > 0){//有数据时,读取4字节判断消息长度
byte[] sizeBytes = new byte[4];
in.mark();//标记当前位置,以便reset
in.get(sizeBytes);//读取前4字节
//NumberUtil是自己写的一个int转byte[]的一个工具类
intsize = NumberUtil.byteArrayToInt(sizeBytes);
//如果消息内容的长度不够则直接返回true
if(size > in.remaining()){//如果消息内容不够,则重置,相当于不读取size
in.reset();
return false;//接收新数据,以拼凑成完整数据
} else{
byte[] bytes = new byte[size];
in.get(bytes, 0, size);
String xmlStr = newString(bytes,"UTF-8");
System.out.println("------------"+xmlStr);
if(null!= xmlStr && xmlStr.length() > 0){
AsResponse resCmd = newAsResponse();
AsXmlPacker.parse(resCmd, xmlStr);
if(resCmd != null){
out.write(resCmd);
}
}
if(in.remaining() > 0){//如果读取内容后还粘了包,就让父类再给俺
一次,进行下一次解析
return true;
}
}
}
return false;//处理成功,让父类进行接收下个包
}
}
下面附上Encode类
public class AsResponseEncoder extends ProtocolEncoderAdapter {
private final Charset charset;
public AsResponseEncoder(Charset charset){
this.charset = charset;
}
public void encode(IoSession session, Object message,
ProtocolEncoderOutput out) throwsException {
CharsetEncoder ce = charset.newEncoder();
IoBuffer buffer = IoBuffer.allocate(100).setAutoExpand(true);
AsResponse respCmd = (AsResponse) message;
String xml = AsXmlPacker.pack(respCmd);//将对象转成xml
byte[] bytes = xml.getBytes();
byte[] sizeBytes = NumberUtil.intToByteArray(bytes.length);
buffer.put(sizeBytes);//将前4位设置成数据体的字节长度
buffer.put(bytes);//消息内容
buffer.flip();
out.write(buffer);
}
}