2012-06-04 1 views
2

У меня очень странная проблема с моей программой, которая использует Netty.Netty CorruptedFrameException с несколькими пакетами соединений прибывает в то же время

Я слушаю порт и разбираю сообщения (используя реализацию FrameDecoder). Все работает нормально, если я получаю одно соединение, но когда я получаю два соединения на одном и том же порту (каждый с другого сервера), я сталкиваюсь с редкой, но критической ситуацией, когда я получаю поврежденноеFrameException

Проблема возникает, когда моя программа получает TCP-пакеты с точно такой же временной метки (при передаче информации на очень высокой скорости) следующим образом

  1. TCP пакет от сервера 1
  2. TCP пакет от сервера 2
  3. TCP пакет от сервера 1 (который является продолжением сообщения, начатого в пуле 1)
  4. TCP пакетов с сервера 2 (который является продолжением сообщения starged в пуле 2)

Моя программа пытается разобрать 1 и 2 в виде сообщения, вместо того, чтобы знать, что фактическое сообщение 1 & 3 и 2 Я где-то читал, что, возможно, мне нужно создать экземпляр нового FrameDecoder для каждого канала, но я не знаю, как именно это сделать. Я добавляю декодер к pipleline при запуске, и я не могу понять, как добавить новый определенный канал

Исключения Я испытывающим являются:

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] 
+0

«Возможно, мне нужно создать экземпляр нового FrameDecoder для каждого канала». Нет, возможно, об этом. Это именно то, что вам нужно сделать. – EJP

+0

Я понял, но как мне это сделать? Я добавляю декодированный объект ChannelPipeLine.addLast («декодер», decoderObject) при инициализации, , но когда подключается новый канал, я нахожусь в точке channelConnected (ChannelHandlerContext ctx, ChannelStateEvent t) ... Если я создаю новый декодер, как его назначить канал? Что-то не хватает в головоломке :) – ArnonSe

+0

Это работа channelpipelinefactory. Определите тот, который создает ваш декодер, а затем либо используйте загрузку (с фабрикой каналов), либо передайте фабрику трубопроводов на фабрику каналов при запросе нового канала. – Nicholas

ответ

1

Вам нужно добавить новый объект кадра декодера в новый канал (второй?). Повторяющееся исключение связано с тем, что вы используете один и тот же канал.

  1. Загрузочный сервер берет завод трубопроводов, который будет настраивать все новые каналы с помощью соответствующих кодеров и декодеров.
  2. Всякий раз, когда удаленный клиент подключается к вашему серверу, он создает собственный объект канала.
  3. В реализации канала PipelineFactory вы используете. Убедитесь, что новый экземпляр декодера кадра создается каждый раз при вызове метода().
  4. Аннотации @Sharable предназначены только для целей документации. Даже если вы его используете, это ничего не повлияет, поскольку это не код/​​логика. Просто маркер, который есть все.
0

Вам нужно «НЕ разделять» FrameDecoder между каналами. FrameDecoder не аннотируется с помощью @Sharable, поэтому вы не можете его использовать. Вот причина вашей проблемы здесь ..

+0

Спасибо. Однако в моем коде нет аннотации @Sharable, но это происходит. Я пытаюсь понять, как реализовать то, что предложили люди в приведенных выше комментариях, но все равно не удастся :) – ArnonSe

+0

Если вы можете ссылаться на пример того, как добавить FrameDecoder к самому каналу, а не к конвейеру (или мне не хватает что-то в моем понимании), или мне нужно создать совершенно новый конвейер? Я попытался сделать channel.getPipeLine(). AddLast («декодер», новый объект), но я получаю «дублирующее» исключение – ArnonSe