我正在尝试使端口统一示例适应我的代码库。我认为我遇到的问题是客户端和服务器之间的通道保持打开状态,直到服务器关闭或客户端完成其任务,或者更具体地说,始终使用相同的管道。因此,从管道中删除统一处理程序的示例中的工作流不起作用。
我在端口统一示例中看到的问题是我的客户端一直在为每个请求预先挂起魔术字节,但是服务器端通道删除了端口统一处理程序,一旦消息被确定为第一个进入的请求是一个有效的协议消息。通道上包含来自客户端的前缀魔术字节的后续消息无法处理,因为统一处理程序不再在管道中消耗魔术字节,导致消息格式错误。
我可以通过将统一处理程序留在管道中来解决这个问题,但是每次嗅探器识别协议时,它都会添加协议处理程序。由于管道在通道的生命周期内是持久的,我不断地一遍又一遍地添加相同的处理程序。通过向通道添加属性以避免向管道重新添加内容,这很容易解决。
现在我看到的问题是消息被分成几个缓冲区。如果客户端发送 2k 字节分成两条消息。第一条消息被正确嗅探并传递给下一个处理程序(具体来说,是 LengthFieldBasedFrameDecoder)。它没有所有的字节,所以它等待其余的。当下一条消息与其余字节一起出现时,因为我无法从管道中删除统一器,我再次嗅探,嗅探失败。
有没有解决方法,或者有更好的方法来完成同样的事情?
更新:
将魔术字节的消耗从统一器中移出似乎是正确的方法,但仍然存在的问题(或似乎是)是动态改变管道在 netty 4 中的工作方式与在 netty 中的工作方式不同3.
我的客户端协议在所有请求前面加上一个字节序列来识别它。在 netty 3 中,我们只是跳过了 ChannelBuffer 中的字节,删除了统一器并添加了适当的协议处理来服务该请求。所有后续请求都发生了同样的事情,并且效果很好。
然而,对于 netty 4,一旦我们从管道中删除了处理魔法字节的处理程序,它就会在 Channel 的生命周期内消失,直到客户端关闭它为止。因此,在管道/ChannelHandlerContext 对于通过通道的每条消息来说似乎都是新的之前,它每次都被重新使用,我认为这就是问题所在。
事实上,这使得这种管道的动态变化在实践中变得困难或不可能。我想要一些东西只消耗每个请求的前 N 个字节,但我不能把它留在管道中,因为分成几个 ByteBuf 的大型请求都会吃掉它们的前 N 个字节,这会严重破坏事情。
更新 2:我认为我现在看到的行为与我在后续主题中提到的有关: 如何管理标识您的协议的前缀字节序列