public class CharsetDecoder implements ProtocolDecoder {
public final Logger log = Logger.getLogger(this.getClass());
private final static Charset charset = Charset.forName("GBK");
// 创建一个不会发生得重复的键值,用来存储一次tcp传输中没有解析完的字节
private final static AttributeKey surplus = new AttributeKey(
CharsetDecoder.class, "surplusBuffer");
@Override
public void decode(IoSession session, IoBuffer in, ProtocolDecoderOutput out)
throws Exception {
// TODO Auto-generated method stub
IoBuffer buff = null;
//查看是否有上次没有用完的字节
IoBuffer bytebuf = (IoBuffer) session.getAttribute(surplus);
if (bytebuf == null || bytebuf.remaining() == 0) {
buff = in;
} else {
buff = IoBuffer.allocate(bytebuf.remaining() + in.remaining());
buff.setAutoExpand(true);
buff.put(bytebuf);
buff.put(in);
buff.flip();
}
if(buff == null)
return ;
if (buff.remaining() >= 4) {
try {
while (buff.hasRemaining()) {
//标记一下读取的位置,如果不对,还要回来
buff.mark();
//读取字节的总长度
int byteLength = buff.getInt();
//判断一下剩下的字节是否满足读取的字节总长度
if (byteLength <= buff.remaining()) {
byte[] bys = new byte[byteLength];
buff.get(bys);
msg = new String(bys, charset);
out.write(msg);
} else {
//如果读取字节不足,保到内存中,下次获取的时候加上。
IoBuffer temp = IoBuffer.allocate(1024)
.setAutoExpand(true);
buff.reset();
temp.put(buff);
temp.flip();
buff.clear();
buff.flip();
session.setAttribute(surplus, temp);
break;
}
}
} catch (OutOfMemoryError e) {
buff.clear();
buff.flip();
session.removeAttribute(surplus);
log.error("字节包异常:" + e.getMessage() + " :" + e.getCause());
return;
}
}
if (buff.hasRemaining()) {
IoBuffer temp = IoBuffer.allocate(1024).setAutoExpand(true);
temp.put(buff);
temp.flip();
buff.clear();
session.setAttribute(surplus, temp);
}
}
@Override
public void dispose(IoSession arg0) throws Exception {
// TODO Auto-generated method stub
}
@Override
public void finishDecode(IoSession arg0, ProtocolDecoderOutput arg1)
throws Exception {
// TODO Auto-generated method stub
}
}