最近做了一个项目,项目中用到Netty来接受一些自定义的报文。
一、背景
tcp是以流的方式进行传输,在流里我们要判断消息的起始位置和结束位置。为了区分消息,往往采用下面的几种方式。
- 消息有固定的长度
- 换行符做分隔
- 用一个特殊的分隔符来分隔
- 在消息头中增加length字段
Netty中针对以上的方案都有已经实现好的解码器作为解决方案。
- 针对有固定长度的消息,Netty提供了FixedlengthFrameDecoder解决。
- 针对以回车换行符作为消息结束符的,Netty提供了LineBasedFrameDecoder。
- 针对以分隔符作为消息结束符的,Netty提供了DelimiterBasedFrameDecoder。
- 针对消息头中的放长度字段来分隔的,Netty提供了LengthFieldBasedFrameDecoder。
其中前三种比较简单。第四种有很多的参数比较复杂。
找到该类其中的一个构造方法,下面会根据一个实例来解释它的各个参数的用法,如下所示:
public LengthFieldBasedFrameDecoder(
int maxFrameLength, int lengthFieldOffset, int lengthFieldLength,
int lengthAdjustment, int initialBytesToStrip, boolean failFast) {
this(
ByteOrder.BIG_ENDIAN, maxFrameLength, lengthFieldOffset, lengthFieldLength,
lengthAdjustment, initialBytesToStrip, failFast);
}
- 第一个参数 maxFrameLength: 指定允许的最大长度
- 第二个参数lengthFieldOffset:长度字段在报文中的偏移量。
- 第三个参数lengthFieldLength: 长度字段的长度。
- 第四个参数lengthAdjustment:长度字段的补偿长度。这个不好理解,下面会根据例子解释。这里先不必深究。
- 第五个参数initialBytesToStrip: 从报文开始位置截取的长度。
- 第六个参数failFast:是指定ToLongFrameException该怎么报出来。当为true时即使流未读但是发现长度超过了我们设置的第一个参数就报错,当为false的时候,只有读超过我们设置的长度的时候才报错。
我们以一个实际的例子,来解释下各个参数,假设报文格式如下表:
语法 |
长度 位数 |
Event_Tag |
8 |
Event Length |
32 |
Event Number |
16 |