在Netty中处理消息时不使用分隔符和消息长度

问题描述

是否可以在没有任何分隔符和消息长度知识的情况下使用netty? 我有以下BytetoMessageDecoder实现:

@requiredArgsConstructor
public class MessageDecoder extends BytetoMessageDecoder {

    private static final String ENCODING = "ascii";

    @Override
    protected void decode(ChannelHandlerContext ctx,ByteBuf byteBuf,List out) throws UnsupportedEncodingException {

        if (!byteBuf.isReadable()) {
            return;
        }
        byte[] bytes = new byte[byteBuf.readableBytes()];
        byteBuf.readBytes(bytes);

        String outString = new String(bytes,ENCODING);
        System.out.println(outString);

        out.add(outString);
    }
}

问题是在读取时byteBuf可能不包含整个消息。因此,该消息可能会分为几部分。 有办法处理吗?

解决方法

从ByteToMessageDecoder类的documentation

通常是帧检测 应该在管道中通过添加一个 DelimiterBasedFrameDecoder,FixedLengthFrameDecoder, LengthFieldBasedFrameDecoder或LineBasedFrameDecoder。

如果需要自定义帧解码器,则需要小心 当用ByteToMessageDecoder实现时。确保有 通过检查缓冲区中足够的字节以获取完整的帧 ByteBuf。可读Bytes()。如果没有足够的字节来完成 框架,返回时不修改阅读器索引以允许更多字节 到达。

所以是的,有一种处理方法,您必须使用文档第一段中列出的帧解码器之一(它们是ByteToMessageDecoder的子类),或者创建自己的自定义解码器。如果创建自己的自定义解码器(扩展了ByteToMessageDecoder),请确保在整个消息到达之前,不要增加缓冲区的读取器索引。

现在在文档中进一步说明:

要在不修改阅读器索引的情况下检查完整的帧,请使用 ByteBuf.getInt(int)之类的方法。一个必须在以下情况下使用阅读器索引 使用ByteBuf.getInt(int)之类的方法。例如打电话 in.getInt(0)假设帧开始于 缓冲区,并非总是如此。使用in.getInt(in.readerIndex()) 代替。

应该提供创建自定义帧解码器所需的所有要素。