Netty: разница между использованием sync () и addListener () - PullRequest
0 голосов
/ 16 февраля 2019

В обработчике сервера у меня есть следующий метод:

private void writeResponse(HttpObject currentObj, ChannelHandlerContext ctx) throws Exception {
    Promise<String> promise = client.run(); // client.run() will return a promise
    // the promise contains the result string I need for http response.
    promise.sync();
    // this method sends http response back, promise.getNow() is the content for the response.
    writeResponse(currentObj, ctx, promise.getNow()); 

}

Этот метод заключается в отправке ответа после получения некоторых данных от клиента (client в коде).И когда я проверял это с помощью браузера, я получал содержимое ответа.

Однако, когда я изменил его на:

private boolean writeResponse(HttpObject currentObj, ChannelHandlerContext ctx) throws Exception {
    Promise<String> promise = client.run();
    promise.addListener(new FutureListener<String>() {
        @Override
        public void operationComplete(Future<String> future) throws Exception {
            if (future.isSuccess()) {
                writeResponse(currentObj, ctx, future.getNow()); // (1)
            } else {
                writeResponse(currentObj, ctx, "FAILED");
            }
        }
    });
}

, он больше не работал.Насколько я понимаю, второй также должен работать, потому что я подтвердил, что код действительно ввел блок (1) (блок if (future.isSuccess())).Но я не получил никакого ответа в браузере.Может кто-нибудь объяснить это немного или указать мне на некоторые ссылки?Я нашел сравнение между await() и addListener в документе, но мне кажется, что они похожи друг на друга по функциям.

Спасибо!

[обновление] Я обнаружил, что это из-за этого метода перегрузки:

private void writeResponse(HttpObject currentObj, ChannelHandlerContext ctx, String content) {
    FullHttpResponse response = new DefaultFullHttpResponse(
            HTTP_1_1, currentObj.decoderResult().isSuccess()? OK : BAD_REQUEST,
            Unpooled.copiedBuffer(content, CharsetUtil.UTF_8));

    response.headers().set(HttpHeaderNames.CONTENT_TYPE, "text/plain; charset=UTF-8");

    if (HttpUtil.isKeepAlive(request)) {
        // Add 'Content-Length' header only for a keep-alive connection.
        response.headers().setInt(HttpHeaderNames.CONTENT_LENGTH, response.content().readableBytes());
        response.headers().set(HttpHeaderNames.CONNECTION, HttpHeaderValues.KEEP_ALIVE);
    }
    ctx.write(response);
}

Я не должен использовать ctx.write (ответ), но использовать ctx.writeAndFlush (ответ).

Сначала яиспользуйте ctx.write (response), потому что у меня есть метод readComplete для выполнения сброса для меня.

public void channelReadComplete(ChannelHandlerContext ctx) {
    ctx.flush();
}

Но кажется, что при использовании addListener вместо sync, channelReadComplete не можетсделать флеш.Есть идеи почему?

1 Ответ

0 голосов
/ 20 февраля 2019

Проблема в том, что вы просто набираете write(...) в своем ChannelFutureListener, а не writeAndFlush(...).Из-за этого ваши записанные данные никогда не будут сброшены в сокет.

channelReadComplete(...) может быть запущено до выполнения ChannelFutureListener, и поэтому вы попадаете в эту ситуацию.

Поэтому для краткости используйте writeAndFlush(...) в слушателе.

...