问题描述
是否可以在没有任何分隔符和消息长度知识的情况下使用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()) 代替。
应该提供创建自定义帧解码器所需的所有要素。