我已阅读Netty Guide,但对ChannelFuture的解释并不多。我发现在应用它时,ChannelFuture是一个复杂的想法。
我要做的是在初始响应之后将消息写入上下文。与典型的请求/响应流程不同。我需要这样的流程:
问题是,如果我这样做,第二次写不会发出:
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是否存在任何潜在问题?
答案 0 :(得分:2)
当然,这也取决于您的“协议”(例如,如果您使用HTTP,则HTTP协议不支持为同一请求发送2个answears)。但是,假设您的协议允许您发送多个响应部分:
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的结果,但两者都是等于)。只需注意operationComplete并不意味着它成功的情况。
答案 1 :(得分:0)
试试这个:
ctx.channel().writeAndFlush(response);
Message newMsg = createMessage();
ctx.channel().writeAndFlush(newMsg);
Channel.write(..)始终从ChannelPipeline的尾部开始。
ChannelHandlerContext.write(...)从ChannelHandler的当前位置开始。
答案 2 :(得分:-1)
#2看起来更好,但一定要测试操作是否成功。如果没有,请使用future.getCause()来访问异常。并不是说它会改变功能,但你可以通过简单地直接在写调用的结果上添加监听器来缩短代码,即。你不需要宣布未来,因为它将在回调中提供。