2013-06-02 2 views
1

До сих пор я был amp'd об обновлении с версии Netty 3.5.7.Final до 4.0.0CR3, пока не столкнулся с моей последней проблемой во время обновления. .. LengthFieldBasedFrameDecoder. Каждый доступный конструктор требует maxFrameLength, который я установил Integer.MAX_VALUE, но при запуске клиента/сервера я получаю несколько трасс стека (один показан ниже), в которых указано, что Integer.MAX_VALUE превышен (2147483647). Я попытался сделать снимок при настройке максимального размера буфера канала, копая через класс ChannelConfig в документах API и других других сообщениях stackoverflow, но не превалирует. Кто-нибудь знает, есть ли отсутствующий параметр, который я могу установить, или способ предотвратить чтение из этого высокого?Netty 4.0.0.CR3 - LengthFieldBasedFrameDecoder maxFrameLength превосходит Integer.MAX_VALUE

Трассировка стека:

io.netty.handler.codec.TooLongFrameException: Adjusted frame length exceeds 2147483647: 4156555235 - discarded 
at io.netty.handler.codec.LengthFieldBasedFrameDecoder.fail(LengthFieldBasedFrameDecoder.java:486) 
at io.netty.handler.codec.LengthFieldBasedFrameDecoder.failIfNecessary(LengthFieldBasedFrameDecoder.java:462) 
at io.netty.handler.codec.LengthFieldBasedFrameDecoder.decode(LengthFieldBasedFrameDecoder.java:397) 
at io.netty.handler.codec.LengthFieldBasedFrameDecoder.decode(LengthFieldBasedFrameDecoder.java:352) 
at io.netty.handler.codec.ByteToMessageDecoder.callDecode(ByteToMessageDecoder.java:111) 
at io.netty.handler.codec.ByteToMessageDecoder.inboundBufferUpdated(ByteToMessageDecoder.java:69) 
at io.netty.channel.ChannelInboundByteHandlerAdapter.inboundBufferUpdated(ChannelInboundByteHandlerAdapter.java:46) 
at io.netty.channel.DefaultChannelHandlerContext.invokeInboundBufferUpdated(DefaultChannelHandlerContext.java:1031) 
at io.netty.channel.DefaultChannelHandlerContext.fireInboundBufferUpdated0(DefaultChannelHandlerContext.java:998) 
at io.netty.channel.DefaultChannelHandlerContext.fireInboundBufferUpdated(DefaultChannelHandlerContext.java:978) 
at io.netty.handler.timeout.IdleStateHandler.inboundBufferUpdated(IdleStateHandler.java:257) 
at io.netty.channel.DefaultChannelHandlerContext.invokeInboundBufferUpdated(DefaultChannelHandlerContext.java:1057) 
at io.netty.channel.DefaultChannelHandlerContext.fireInboundBufferUpdated0(DefaultChannelHandlerContext.java:998) 
at io.netty.channel.DefaultChannelHandlerContext.fireInboundBufferUpdated(DefaultChannelHandlerContext.java:978) 
at io.netty.channel.DefaultChannelPipeline.fireInboundBufferUpdated(DefaultChannelPipeline.java:828) 
at io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:118) 
at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:429) 
at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:392) 
at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:322) 
at io.netty.util.concurrent.SingleThreadEventExecutor$2.run(SingleThreadEventExecutor.java:114) 
at java.lang.Thread.run(Thread.java:680) 

Мой клиент настроен как следует:

peerClient.bootstrap = new Bootstrap(); 

peerClient.bootstrap.group(new NioEventLoopGroup()) 
      .channel(NioSocketChannel.class) 
      .option(ChannelOption.ALLOCATOR, UnpooledByteBufAllocator.DEFAULT) 
      .option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 120000) 
      .option(ChannelOption.SO_KEEPALIVE, true) 
      .option(ChannelOption.TCP_NODELAY, true) 
      .option(ChannelOption.SO_REUSEADDR, true) 
      .handler(PeerInitializer.newInstance()); 

Моя конфигурация сервера:

result.serverBootstrap = new ServerBootstrap(); 

result.serverBootstrap.group(new NioEventLoopGroup(), new NioEventLoopGroup()) 
     .channel(NioServerSocketChannel.class) 
     .handler(new LoggingHandler(LogLevel.INFO)) 
     .childHandler(PeerInitializer.newInstance()) 
     .childOption(ChannelOption.ALLOCATOR, UnpooledByteBufAllocator.DEFAULT); 

Метод initChannel переопределены с помощью пользовательского класса, простирающейся ChannelInitializer

public class PeerInitializer extends ChannelInitializer<SocketChannel> 

@Override 
protected void initChannel(SocketChannel ch) throws Exception { 
    final ChannelPipeline pipeline = ch.pipeline(); 

    pipeline.addLast(
      messageEncoder, 
      HandshakeDecoder.newInstance(), 
      connectionHandler, 
      handshakeHandler, 
      new LengthFieldBasedFrameDecoder(Integer.MAX_VALUE, 0, 4), 
      messageHandler); 
} 

ответ

0

В Netty, преобразование 4 байта длины поля в беззнаковое Int (на самом деле долгое)

LengthFieldBasedFrameDecoder.java

private long getFrameLength(ByteBuf in, int actualLengthFieldOffset) { 
    in = in.order(byteOrder); 
    long frameLength; 
    switch (lengthFieldLength) { 
    case 1: 
     frameLength = in.getUnsignedByte(actualLengthFieldOffset); 
     break; 
    case 2: 
     frameLength = in.getUnsignedShort(actualLengthFieldOffset); 
     break; 
    case 3: 
     frameLength = in.getUnsignedMedium(actualLengthFieldOffset); 
     break; 
    // This Code 
    case 4: 
     frameLength = in.getUnsignedInt(actualLengthFieldOffset); 
     break; 
    case 8: 
     frameLength = in.getLong(actualLengthFieldOffset); 
     break; 
    default: 
     throw new Error("should not reach here"); 
    } 
    return frameLength; 
} 

AbstractByteBuf.java

@Override 
public long getUnsignedInt(int index) { 
    return getInt(index) & 0xFFFFFFFFL; 
} 

4156555235 является -138412061.

Код:

int i = 0xF7BFFFE3; 
System.out.println(i); 

Убедитесь, что значение поля длины.

Попробуйте это:

Вашего ChannelInitializer

public class PeerInitializer extends ChannelInitializer<SocketChannel> 

@Override 
protected void initChannel(SocketChannel ch) throws Exception { 
    final ChannelPipeline pipeline = ch.pipeline(); 

    pipeline.addLast(
      new ByteLoggingHandler(LogLevel.INFO), // add 
      messageEncoder, 
      HandshakeDecoder.newInstance(), 
      connectionHandler, 
      handshakeHandler, 
      new LengthFieldBasedFrameDecoder(Integer.MAX_VALUE, 0, 4), 
      messageHandler); 
} 

Надеется, что это помогает.

Смежные вопросы