0

I'm trying to implement some kind of http proxy in netty and for this i need to send several files from the disk one by one. For that i implemented simple ChannelFutureListener that on 'operationComplete' sends next file:

public class FrontendArchive implements ChannelFutureListener {
    private final ChannelHandlerContext ctx;
    private final Archive archive;

    public void sendNext() {
        Entity entity = archive.nextEntity();
        if (entity == null) {
            //No more data
            // Write the end marker
            ctx.writeAndFlush(LastHttpContent.EMPTY_LAST_CONTENT).addListener(ChannelFutureListener.CLOSE);
            return;
        }

        try {
            ctx.writeAndFlush(entity.getData()).addListener(this);
        } catch (IOException e) {
            //We have nothing to do atm, but break the connection.
            log.error("Exception: {}", e.getMessage(), e);
            ctx.writeAndFlush(LastHttpContent.EMPTY_LAST_CONTENT).addListener(ChannelFutureListener.CLOSE);
        }
    }


    @Override
    public void operationComplete(ChannelProgressiveFuture channelProgressiveFuture) throws Exception {
        this.sendNext();
    }
}

And getData is quite simple:

public Object getData() throws IOException {
try(RandomAccessFile raf = new RandomAccessFile(new File(this.getLocation()), "r")) {
    long fileLength = raf.length();

    // Write the content.
    return new ChunkedFile(raf, 0, fileLength, SEND_BUFFER);
}
}

The problem is that for some reason listener's 'operationCompleted' is only called for first couple of files and actual data is never received on the other side. What i'm doing wrong?

akashihi
  • 917
  • 2
  • 9
  • 19

1 Answers1

0

Well, netty is smart enought to queue write requests and them them automatically. So, the code above could be simplified to:

    // Start sending data.
    Entity entity = archive.get().nextEntity();
    try {
        while (entity != null) {
            ctx.write(entity.getData());
            entity = archive.get().nextEntity();
        }
    } catch (IOException e) {
        log.error("Exception during zip serving: {}", e.getMessage(), e);
    } finally {
        ctx.writeAndFlush(LastHttpContent.EMPTY_LAST_CONTENT).addListener(ChannelFutureListener.CLOSE);
    }

You don't have to wait for transfer completion and allowed to queue all the transmissions at once.

akashihi
  • 917
  • 2
  • 9
  • 19