Netty编解码器!

半包和粘包

半包问题:

指一个完整的应用层消息被分成多个 TCP 数据包发送,接收端在一次读取操作中只接收到消息的一部分

  • 例如,发送端发送了一条 100 字节的消息,但由于网络原因,这条消息被拆分成了两个 TCP 数据包

    • 一个 60 字节,另一个 40 字节
  • 接收端可能在第一次读取时只接收到前 60 字节的数据,剩下的 40 字节需要在后续的读取操作中才能接收到

粘包问题:

粘包问题是指多个应用层消息在传输过程中被粘在一起,接收端在一次读取操作中接收到大于 1个 消息的情况

  • 例如,发送端发送了两条消息,每条 50 字节,但接收端在一次读取操作中收到了 80 字节的数据,超过了 1条 消息的内容

解码器

固定长度解码器:FixedLengthFrameDecoder:

直接通过构造函数设置固定长度的大小 frameLength

  • 无论接收方一次获取多大的数据,都会严格按照 frameLength 进行解码

  • 如果累积读取到长度大小为 frameLength 的消息,那么解码器认为已经获取到了一个完整的消息

如果消息长度小于 frameLength:

  • FixedLengthFrameDecoder 解码器会一直等后续数据包的到达,直至获得完整的消息
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public class FixedLengthFrameDecoder extends ByteToMessageDecoder {
private final int frameLength;

public FixedLengthFrameDecoder(int frameLength) {
this.frameLength = frameLength;
}

@Override
protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception {
while (in.readableBytes() >= frameLength) {
ByteBuf buf = in.readBytes(frameLength);
out.add(buf);
}
}
}

特殊分隔符解码器:DelimiterBasedFrameDecoder

  • 基于换行符解码器和自定义分隔符解码器(比如 特殊字符)来划分消息边界,从而解决半包和粘包问题
    • 使用者可以根据自己的需求灵活确定分隔符

长度域解码器:LengthFieldBasedFrameDecoder

  • 基于长度字段的解码器是指在消息头部添加长度字段,指示消息的总长度