2016-09-01 6 views
1

Я читал Netty Guide, это не объясняет многое на ChannelFuture. Я считаю, что ChannelFuture - это сложная идея при ее применении.Как работает Netty ChannelFuture?

То, что я пытаюсь сделать, - написать сообщение в контекст после его первоначального ответа. В отличие от типичного потока запросов/ответов. Мне нужен поток, как это:

  1. клиента отправить запрос -> сервер (Нетти)
  2. Сервер отправляет ответ с ctx.writeAndFlush (МВП);
  3. Сервер отправляет еще одно сообщение этому ctx после того, как шаг 2 завершен.

Проблема заключается в том, что если я делаю что-то вроде этого, то вторая запись не будет посылать:

ctx.writeAndFlush(response); 
Message newMsg = createMessage(); 
ctx.writeAndFlush(newMsg); //will not send to client 

Тогда я пытаюсь использовать ChannelFuture, он работает, но я не уверен, если я логически исправить:

ChannelFuture msgIsSent = ctx.writeAndFlush(response); 
if(msgIsSent.isDone()) 
{ 
    Message newMsg = createMessage(); 
    ctx.writeAndFlush(newMsg); //this works 
} 

или следует использовать вместо этого ChannelFutureListener()?

ChannelFuture msgIsSent = ctx.writeAndFlush(response); 
msgIsSent.addListener(new ChannelFutureListener(){ 
@Override 
public void operationComplete(ChannelFuture future) 
    { 
     Message newMsg = createMessage(); 
     ctx.writeAndFlush(newMsg); 
    } 
}); 

Будет ли это также работать?

Какой подход является наилучшей практикой? Есть ли потенциальная проблема с использованием метода 2?

ответ

2

Конечно, это тоже зависит от вашего «протокола» (что означает, например, если вы используете HTTP, отправка 2-х сообщений для одного и того же запроса не поддерживается протоколом HTTP). Но позвольте сказать, что ваш протокол позволяет отправлять несколько частей ответа:

Netty добавить сообщения для отправки в трубопровод, соблюдая порядок.

Таким образом, в первом примере, я немного удивлен, что не работает:

ctx.writeAndFlush(response); 
Message newMsg = createMessage(); 
ctx.writeAndFlush(newMsg); // should send the message 

Однако это может быть привести ваш протокол.Например, это может произойти:

response in message queue to send 
flush not yet done 
newMsg in message queue to send 
flush now come but protocol does not support 2 messages so only send first one 

Так что, если ваш протокол должен признать, что первое сообщение посылается уже, то вам придется ждать первый, так что делать что-то вроде:

ctx.writeAndFlush(response).addListener(new ChannelFutureListener() { 
    @Override 
    public void operationComplete(ChannelFuture future) { 
    if (future.isDone()) { 
     Message newMsg = createMessage(); 
     ctx.writeAndFlush(newMsg); 
    } else { // an error occurs, do perhaps something else 
    } 
    } 
}); 

Так что ваши последнее предложение (я просто не создаю ChannelFuture, но напрямую использовал результат writeAndFlush, но оба равны). Просто позаботьтесь о том, что операцияComplete не означает, что она в успехе.

-1

# 2 выглядит лучше, но обязательно проверьте, была ли операция успешной. Если нет, используйте функцию future.getCause() для доступа к исключению. Не то, чтобы это изменило функциональность, но вы можете сократить код, просто добавив слушателя непосредственно к результату вызова записи, I.e. вам не нужно декларировать будущее, поскольку оно будет предоставлено в обратном вызове.

0

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

ctx.channel().writeAndFlush(response); 
    Message newMsg = createMessage(); 
    ctx.channel().writeAndFlush(newMsg); 

Channel.write (..) всегда начинается с хвоста ChannelPipeline.

ChannelHandlerContext.write (...) начинается с текущей позиции ChannelHandler.

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