Я перехожу с raw NIO на netty. Ответ, который мне нужно отправить обратно, выглядит следующим образом

short
long
long
long
file

У меня есть следующий рабочий пример, и мне было интересно, как переместить FileRegion в кодировщик.

MessageToByteEncoder

@Override
protected void encode(final ChannelHandlerContext ctx, final BlockResponse msg,
    final ByteBuf out) throws Exception {
  out.writeShort(DataServerMessage.DATA_SERVER_RESPONSE_MESSAGE);
  out.writeLong(msg.getBlockId());
  out.writeLong(msg.getOffset());
  out.writeLong(msg.getLength());
}

ChannelInboundHandlerAdapter

    ctx.write(new BlockResponse(blockId, offset, readLength));
    FileChannel channel = closer.register(file.getChannel());
    ChannelFuture future = ctx.writeAndFlush(new DefaultFileRegion(channel, offset, readLength));
    future.addListener(ChannelFutureListener.CLOSE);

Я думаю, что если бы я написал в адаптере для ответа writeAndFlush (и поместил туда файл), то я мог бы сделать еще один writeAndFlush в кодировщике, но тогда кодировщик должен был бы закрыть его. Есть другой способ?

Благодарность!

РЕДАКТИРОВАТЬ:

Вот обновленный код, который работает:

public static final class Encoder extends MessageToMessageEncoder<BlockResponse> {
  private static final int HEADER_LENGTH = 2 + 4 * 3; // short, 3 longs

  @Override
  protected void encode(final ChannelHandlerContext ctx, final BlockResponse msg,
      final List<Object> out) throws Exception {
    out.add(createHeader(ctx, msg));
    if (msg.getChannel() != null) {
      out.add(new DefaultFileRegion(msg.getChannel(), msg.getOffset(), msg.getLength()));
    }
  }

  private ByteBuf createHeader(final ChannelHandlerContext ctx, final BlockResponse msg) {
    ByteBuf header = ctx.alloc().buffer(HEADER_LENGTH);
    header.writeShort(DataServerMessage.DATA_SERVER_RESPONSE_MESSAGE);
    header.writeLong(msg.getBlockId());
    header.writeLong(msg.getOffset());
    header.writeLong(msg.getLength());
    return header;
  }
}

ChannelInboundHandlerAdapter

ChannelFuture future =
    ctx.writeAndFlush(new BlockResponse(blockId, offset, readLength, channel));
future.addListener(ChannelFutureListener.CLOSE);
future.addListener(new ClosableResourceChannelListener(file));
0
ekaqu 19 Авг 2014 в 03:55

1 ответ

Лучший ответ

Если вам нужно также запустить FileRegion из кодировщика, вам нужно использовать MessageToMessageEncoder и выделить ByteBuf своим собственным внутри там.

1
Norman Maurer 19 Авг 2014 в 08:48
Итак, заголовок я выделяю себе (из ctx) и отправляю как out.add (header), затем я говорю out.add (fileRegion)? Я попробую, спасибо!
 – 
ekaqu
19 Авг 2014 в 22:49