Netty MessageToByteEncoder测试时readOutbound始终返回null
问题原因
- 核心原因:
EmbeddedChannel的writeOneOutbound()方法仅会执行出站写入逻辑,不会自动触发flush操作。编码完成的ByteBuf会停留在Channel的出站缓冲区,不会进入可供readOutbound()读取的队列,因此读取结果始终为null。 - 潜在隐患:编码器中调用
s.getBytes()未指定字符集,会使用JVM默认字符集执行转换,不符合协议约定的ASCII编码规则,跨环境运行时可能出现内容解析错误。
修复方案
修正测试代码
两种改法二选一即可:
- 写入后手动执行flush:
@Test public void encode03 () { EmbeddedChannel channel = new EmbeddedChannel(new MessageOutboundEncoder()); String s = "Howdy"; channel.writeOneOutbound(s); // 触发flush将缓冲数据推到出站读取队列 channel.flush(); ByteBuf byteBuf = channel.readOutbound(); assert(byteBuf != null); // 测试用例也需遵循Netty ByteBuf资源释放规范,避免内存泄漏 byteBuf.release(); }
- 直接使用自带flush逻辑的
writeOutbound()方法:
@Test public void encode03 () { EmbeddedChannel channel = new EmbeddedChannel(new MessageOutboundEncoder()); String s = "Howdy"; // writeOutbound写入完成后会自动触发flush channel.writeOutbound(s); ByteBuf byteBuf = channel.readOutbound(); assert(byteBuf != null); byteBuf.release(); }
修正编码器的编码逻辑
明确指定使用ASCII字符集转换字符串,同时长度字段写入实际字节数组长度,避免后续扩展时出现长度计算错误:
import java.nio.charset.StandardCharsets; public class MessageOutboundEncoder extends MessageToByteEncoder<String> { @Override protected void encode(ChannelHandlerContext channelHandlerContext, String s, ByteBuf byteBuf) throws Exception { byte[] contentBytes = s.getBytes(StandardCharsets.US_ASCII); byteBuf.writeShort(contentBytes.length); byteBuf.writeBytes(contentBytes); } }
补充说明:协议中2字节长度字段为无符号类型时,单帧ASCII内容长度不能超过65535,否则会出现长度值溢出问题。
内容的提问来源于stack exchange,提问作者Clark Hobbie
相关产品推荐
相关产品推荐

