接下来介绍netty如何切割分包
学习目的,了解处理业务,方便以后脱离依赖
读者如果不感兴趣或看不懂可以先忽略,难度比较大
LengthFieldBasedFrameDecoder.class
public LengthFieldBasedFrameDecoder( ByteOrder byteOrder, //大小端模式 默认大端 ByteOrder BIG_ENDIAN int maxFrameLength, //包Frame netty叫帧概念 最大上限 int lengthFieldOffset, //包长度信息偏移多少bytes int lengthFieldLength, //包长度单位为bytes int lengthAdjustment, //包附加信息占多少位,如包尾部checksum 也可以不用设置 int initialBytesToStrip,//忽悠包头信息,返给上层时会去掉这部份bytes boolean failFast) //解包出错,控制抛异常,默认为true 无需关心这选项
如示例
int maxFrameLength = Short.MAX_VALUE; int lengthFieldOffset =1; int lengthFieldLength =2; new LengthFieldBasedFrameDecoder(ByteOrder.BIG_ENDIAN,maxFrameLength,lengthFieldOffset,lengthFieldLength,0,0,true);
如图:
数据包由低到高是从左到右
红色部份lengthFieldOffset 1byte=8bits
蓝色部份lengthFieldLength 2byte=16bits = short
粉色部份messageLength 2byte 读取 蓝色部份由于大端模式 高位 0000 0010 等于2
图2
消息长度为1byte
解读netty源码
分四部份
1.netty解码介绍
2.边界判断
3.计算逻辑
4.切割包
第一部份
先看下LengthFieldBasedFrameDecoder继承类之间的关系
ByteToMessageDecoder处理比较复杂,先不考虑
其实解码只要工作方法是
protected Object decode(ChannelHandlerContext ctx, ByteBuf in) throws Exception
//公开调用方法 out 是解码后保存返回,为什么是个数组?原因有可能出现粘包情况多次解码,合并结果一次返回上层业务 protected final void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception { //调用实现解码方法 Object decoded = decode(ctx, in); if (decoded != null) { out.add(decoded); } }
提示:如果自己实现解码 继承ByteToMessageDecoder类,逻辑写在decode(ChannelHandlerContext ctx, ByteBuf in)方法即可
第三部份
1 //计算包长度偏移坐标 已读坐标+lengthFieldOffset参数 2 int actualLengthFieldOffset = in.readerIndex() + lengthFieldOffset; 3 //算出包长度 4 long frameLength = getUnadjustedFrameLength(in, actualLengthFieldOffset, lengthFieldLength, byteOrder); 5 6 //包实际长度 加上开始忽悠的 lengthFieldEndOffset参数 加上 lengthAdjustment 参数 7 frameLength += lengthAdjustment + lengthFieldEndOffset; 8 9 //跳过忽悠头部 initialBytesToStrip参数 10 in.skipBytes(initialBytesToStrip); 11 12 //length 单位是byte 如2 是占一个short长度 4占int长度 8占long长度 13 protected long getUnadjustedFrameLength(ByteBuf buf, int offset, int length, ByteOrder order) { 14 //转换大小端模式 15 buf = buf.order(order); 16 long frameLength; 17 switch (length) { 18 case 1: 19 frameLength = buf.getUnsignedByte(offset); 20 break; 21 case 2: 22 frameLength = buf.getUnsignedShort(offset); 23 break; 24 case 3: 25 frameLength = buf.getUnsignedMedium(offset); 26 break; 27 case 4: 28 frameLength = buf.getUnsignedInt(offset); 29 break; 30 case 8: 31 frameLength = buf.getLong(offset); 32 break; 33 default: 34 throw new DecoderException( 35 "unsupported lengthFieldLength: " + lengthFieldLength + " (expected: 1, 2, 3, 4, or 8)"); 36 } 37 return frameLength; 38 }