在我们的应用程序中,我们有一个客户端/服务器对,用一个小的握手协议P1启动它们的连接,之后它们切换到另一个协议P2。
对于P1协议,使用以下处理程序初始化管道:
LengthFieldBasedFrameDecoder
P1ProtocolMessageDecoder
LengthFieldPrepender
P1ProtocolMessageEncoder
P1握手协议成功完成后,流量应切换到P2协议,在这种情况下,我们首先清除管道,然后添加一组单独的处理程序
P2MessageDecoder
P2MessageEncoder
IdleHandler
当收到P1协议中的最后一条预期消息时,切换管道:
// switch traffic to P2 protocol
clearPipeline();
addNewHandlers();
遇到的问题是LengthFieldBasedFrameDecoder删除触发了意外的读取(因为在处理程序的ByteBuf中未读取的字节数)。但是,由于在那个时间点,管道是空的(已清除,但尚未添加新的处理程序),入站消息将被删除。
有没有"安全"在处理程序不到位的时候进行管道切换而不触发不需要的读取的方法呢?
由于
稍后编辑:
我在这里阅读了有关更换解码器的信息: (标题为&#34的部分;用管道中的另一个解码器替换解码器")
http://netty.io/4.0/api/io/netty/handler/codec/ReplayingDecoder.html
我成功应用的解决方法是:
removeOldNonByteToMessageHandlers();
addNewHandlers()
removeOldByteToMessageHandlers();
// when the "leftover bytes" read is triggered the new handlers are already in place
我的解决方案看起来很糟糕。 有没有更好的" netty-er"实现这个目标的方式?
答案 0 :(得分:1)
我注意到删除顺序中的ByteToMessage处理程序对我来说还不够,因为它仍然会尝试将它们用于当前消息中的剩余字节。
在我的情况下,我有一个FixedLengthFrameDecoder,我想在读取指定的字节数后切换一个LengthFieldBasedFrameDecoder。
如果我的消息是X字节,Y的第一个字节是protocole信号,或“握手”,Z是剩余字节的数量,我想用ByteToMessage处理程序读取第一个Y,然后是Z下一个字节由新的处理程序。
@Override
protected Object decode(ChannelHandlerContext ctx, ByteBuf in) throws Exception {
Object handshake = super.decode(ctx, in);
ctx.pipeline().addFirst(new LengthFieldBasedFrameDecoder(ByteOrder.BIG_ENDIAN, Integer.MAX_VALUE, 0, 4, 0, 4, true));
if (in.isReadable()) {
Object[] response = new Object[] { in.readBytes(in.readableBytes())};
ctx.pipeline().remove(this);
return response;
} else {
ctx.pipeline().remove(this);
return handshake;
}
}