【问题标题】:Netty CorruptedFrameException with multiple connection packets arrive at the same time多个连接包同时到达的 Netty CorruptedFrameException
【发布时间】:2012-06-08 08:11:15
【问题描述】:

我在使用 Netty 的程序中遇到了一个非常奇怪的问题。

我正在监听一个端口并解析消息(使用 FrameDecoder 实现)。如果我收到一个连接,一切正常,但是当我在同一个端口上收到两个连接(每个来自不同的服务器)时,我遇到了一种罕见但严重的情况,我得到了损坏的FrameException

当我的程序接收到具有完全相同时间戳的 TCP 数据包(以非常高的速率发送信息时)时,会出现如下问题

  1. 来自服务器 1 的 TCP 数据包
  2. 来自服务器 2 的 TCP 数据包
  3. 来自服务器 1 的 TCP 数据包(这是在项目符号 1 中开始的消息的延续)
  4. 来自服务器 2 的 TCP 数据包(这是项目符号 2 中开始的消息的延续)

我的程序尝试将 1 和 2 解析为消息,而不是知道实际消息是 1 & 3 和 2 & 4 我在某处读到,也许我需要为每个通道连接实例化一个新的 FrameDecoder,但我不知道该怎么做。我在启动时将解码器添加到管道中,但我无法弄清楚如何将新解码器添加到特定通道

我遇到的例外情况是:

org.jboss.netty.handler.codec.frame.CorruptedFrameException: Adjusted frame length (0) is less than lengthFieldEndOffset: 2
    at org.jboss.netty.handler.codec.frame.LengthFieldBasedFrameDecoder.decode(LengthFieldBasedFrameDecoder.java:340) ~[netty-3.1.5.GA.jar:]
    at org.jboss.netty.handler.codec.frame.FrameDecoder.callDecode(FrameDecoder.java:282) ~[netty-3.1.5.GA.jar:]
    at org.jboss.netty.handler.codec.frame.FrameDecoder.messageReceived(FrameDecoder.java:214) ~[netty-3.1.5.GA.jar:]
    at org.jboss.netty.channel.Channels.fireMessageReceived(Channels.java:345) ~[netty-3.1.5.GA.jar:]
    at org.jboss.netty.channel.Channels.fireMessageReceived(Channels.java:332) ~[netty-3.1.5.GA.jar:]
    at org.jboss.netty.channel.socket.nio.NioWorker.read(NioWorker.java:323) ~[netty-3.1.5.GA.jar:]
    at org.jboss.netty.channel.socket.nio.NioWorker.processSelectedKeys(NioWorker.java:275) ~[netty-3.1.5.GA.jar:]
    at org.jboss.netty.channel.socket.nio.NioWorker.run(NioWorker.java:196) ~[netty-3.1.5.GA.jar:]
    at org.jboss.netty.util.internal.IoWorkerRunnable.run(IoWorkerRunnable.java:46) ~[netty-3.1.5.GA.jar:]
    at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:651) [na:1.5.0]
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:676) [na:1.5.0]
    at java.lang.Thread.run(Thread.java:595) [na:1.5.0]

org.jboss.netty.handler.codec.frame.TooLongFrameException: Adjusted frame length exceeds 4096: 8224
        at org.jboss.netty.handler.codec.frame.LengthFieldBasedFrameDecoder.decode(LengthFieldBasedFrameDecoder.java:296) ~[netty-3.1.5.GA.jar:]
        at org.jboss.netty.handler.codec.frame.FrameDecoder.callDecode(FrameDecoder.java:282) ~[netty-3.1.5.GA.jar:]
        at org.jboss.netty.handler.codec.frame.FrameDecoder.messageReceived(FrameDecoder.java:216) ~[netty-3.1.5.GA.jar:]
        at org.jboss.netty.channel.Channels.fireMessageReceived(Channels.java:345) ~[netty-3.1.5.GA.jar:]
        at org.jboss.netty.channel.Channels.fireMessageReceived(Channels.java:332) ~[netty-3.1.5.GA.jar:]
        at org.jboss.netty.channel.socket.nio.NioWorker.read(NioWorker.java:323) ~[netty-3.1.5.GA.jar:]
        at org.jboss.netty.channel.socket.nio.NioWorker.processSelectedKeys(NioWorker.java:275) ~[netty-3.1.5.GA.jar:]
        at org.jboss.netty.channel.socket.nio.NioWorker.run(NioWorker.java:196) ~[netty-3.1.5.GA.jar:]
        at org.jboss.netty.util.internal.IoWorkerRunnable.run(IoWorkerRunnable.java:46) ~[netty-3.1.5.GA.jar:]
        at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:651) [na:1.5.0]
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:676) [na:1.5.0]
        at java.lang.Thread.run(Thread.java:595) [na:1.5.0]

【问题讨论】:

  • “也许我需要为每个通道实例化一个新的 FrameDecoder”。不,也许关于它。这正是您需要做的。
  • 我想,但我该怎么做呢?我在初始化时在 ChannelPipeLine object.addLast("decoder", decoderObject) 上添加解码,但是当连接新通道时,我在 channelConnected(ChannelHandlerContext ctx, ChannelStateEvent t) ... 如果我实例化一个新的解码器,如何将其分配给通道?谜题中缺少一些东西:)
  • 这是通道管道工厂的工作。定义一个创建解码器的解码器,然后在请求新通道时使用引导程序(使用通道工厂)或将管道工厂传递给通道工厂。

标签: java exception frame netty decoder


【解决方案1】:

您需要将帧解码器的new 对象添加到您的new(第二个?)通道。重复异常是因为您使用的是同一频道。

  1. 服务器引导程序采用管道工厂,它将使用适当的编码器和解码器配置所有新通道。
  2. 每当远程客户端连接到您的服务器时,它都会创建自己的通道对象。
  3. 在您正在使用的 Channel PipelineFactory 实现中。确保每次调用 pipeline() 方法时都会创建新实例的帧解码器。
  4. @Shareable 注释仅用于文档目的。即使您使用它,它也不会影响任何事情,因为它不是代码/逻辑。只是一个标记而已。

【讨论】:

    【解决方案2】:

    您需要在通道之间“不共享”FrameDecoder。 FrameDecoder 未使用 @Sharable 注释,因此您无法共享它。这就是你的问题的原因在这里..

    【讨论】:

    • 谢谢。但是,我的代码中没有 @Shareable 注释,它仍然会发生。我正在尝试了解如何实施上述 cmets 中的人所建议的内容,但仍然没有运气:)
    • 如果您可以链接到如何将 FrameDecoder 添加到通道本身而不是管道(或者我在我的理解中遗漏了什么)的示例,或者我是否需要创建一个全新的管道?我试过做 channel.getPipeLine().addLast("decoder",new object) 但我得到一个“重复”异常
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-12-20
    • 2011-07-25
    • 1970-01-01
    • 1970-01-01
    • 2012-02-15
    相关资源
    最近更新 更多