在与硬件打交道的通信中会经常遇到找不到合适的过滤器来接受服务传来的信息,为了解决这个问题,在网上找了很多资料,最后总结出一个自定义过滤器。我现在要用的是接收byte[]。
自定义一个过滤器只需要对应继承的三个文件
- ProtocolCodecFactory
- ProtocolEncoderAdapter
- CumulativeProtocolDecoder
工厂就不用多说了,ProtocolEncoderAdapter 不做处理 直接输出
public class ByteArrayEncoder extends ProtocolEncoderAdapter {
@Override
public void encode(IoSession session, Object message, ProtocolEncoderOutput out) throws Exception {
out.write(message);
out.flush();
}
}
最重要的是继承 CumulativeProtocolDecoder的适配文件
@Override
protected boolean doDecode(IoSession session, IoBuffer in, ProtocolDecoderOutput out) throws Exception {
if (in.remaining() > 1) {// 前1字节是包头
// 标记当前position的快照标记mark,以便后继的reset操作能恢复position位置
in.mark();
if (!isComplete) {
byte[] l = new byte[header];
//我的第一位是len位
in.get(l);
// 取包体数据长度
len = l[0]&0xff; ; // 将byte转成INT
System.out.println("Len:"+len);
}
// 注意上面的get操作会导致下面的remaining()值发生变化
if (in.remaining() < len-1) {
// 如果消息内容不够,则重置恢复position位置到操作前,进入下一轮, 接收新数据,以拼凑成完整数据
in.reset();
return false;
} else {
// 消息内容足够
in.reset();// 重置恢复position位置到操作前
int sumlen = len;
byte[] packArr = new byte[sumlen];
in.get(packArr, 0, sumlen);
IoBuffer buffer = IoBuffer.allocate(sumlen);
buffer.put(packArr);
buffer.flip();
out.write(buffer);
buffer.free();
if (in.remaining() > 0) {
// 如果读取一个完整包内容后还粘了包,就让父类再调用一次,进行下一次解析
return true;
}
}
}
return false;// 处理成功,让父类进行接收下个包
}