1. ByteToMessageDecoder
这个类是解码器的基类,其中描述了解码器基本的工作方式和实现原理;;还定义了一个解码的抽象方法decode,这个方法由业务实现,负责将一段字节数据解码为具体的消息对象。
// 存储接收到的数据
ByteBuf cumulation;
private boolean first; @Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
if (msg instanceof ByteBuf) {
CodecOutputList out = CodecOutputList.newInstance();
try {
ByteBuf data = (ByteBuf) msg; first = cumulation == null;
if (first) {
// 如果 ByteBuf 为空,则将 ByteBuf 指向接收到的消息
cumulation = data;
} else {
// 如果 ByteBuf 不为空,则将接收到的数据追加到 ByteBuf
cumulation = cumulator.cumulate(ctx.alloc(), cumulation, data);
}
// 解码 ByteBuf 中的数据
callDecode(ctx, cumulation, out);
} catch (DecoderException e) {
throw e;
} catch (Throwable t) {
throw new DecoderException(t);
} finally {
// ByteBuf 中的数据被消费完后,重置消费次数,释放内存,ByteBuf置为null
if (cumulation != null && !cumulation.isReadable()) {
numReads = 0;
cumulation.release();
cumulation = null;
// ByteBuf 被消费16后压缩消息
} else if (++ numReads >= discardAfterReads) { numReads = 0;
discardSomeReadBytes();
}
// 将解码得到的报文对象全部分发下去
int size = out.size();
decodeWasNull = !out.insertSinceRecycled();
fireChannelRead(ctx, out, size);
out.recycle();
}
} else {
ctx.fireChannelRead(msg);
}
} // 解码 ByteBuf
protected void callDecode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) {
try {
// 如果 ByteBuf 有可读数据就继续解码
while (in.isReadable()) { // 如果 out 中有内容,则将内容分发出去,然后清空 out, 并将 outSize 置为 0
int outSize = out.size(); if (outSize > 0) {
// 将 out 中的所有消息分发出去
fireChannelRead(ctx, out, outSize);
// out 存储解码后的报文对象
// 清空容器()
out.clear(); if (ctx.isRemoved()) {
break;
}
outSize = 0;
}
// 解码之前的可读长度
int oldInputLength = in.readableBytes();
// 调用自定义的解码器
decode(ctx, in, out); if (ctx.isRemoved()) {
break;
}
// 由上面可知,outSize 为0 ,
// 没有读取数据,没有得到消息对象,则跳出循环
if (outSize == out.size()) {
if (oldInputLength == in.readableBytes()) {
break;
} else {
continue;
}
}
// 没有读取数据,却得到自定义的消息对象,抛出异常
if (oldInputLength == in.readableBytes()) {
throw new DecoderException(
StringUtil.simpleClassName(getClass()) +
".decode() did not read anything but decoded a message.");
} if (isSingleDecode()) {
break;
}
}
} catch (DecoderException e) {
throw e;
} catch (Throwable cause) {
throw new DecoderException(cause);
}
}