Netty ChannelFuture 如何运作?
How Netty ChannelFuture works?
我看过Netty Guide,它对ChannelFuture 的解释不多。我发现 ChannelFuture 在应用时是一个复杂的想法。
我想做的是在初始响应后将消息写入上下文。不同于典型的 request/response 流程。我需要这样的流程:
- 客户端发送请求->服务器(netty)
- 服务器发送响应 ctx.writeAndFlush(msg);
- 服务器在第 2 步完成后向该 ctx 发送更多消息。
问题是,如果我这样做,第二次写入不会发送出去:
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 看起来更好,但请确保测试操作是否成功。如果不是,请使用 future.getCause() 访问异常。并不是说它会改变功能,而是您可以通过直接在 write 调用的结果上直接添加侦听器来缩短代码,即您不需要声明未来本身,因为它将在回调中提供。
试试这个:
ctx.channel().writeAndFlush(response);
Message newMsg = createMessage();
ctx.channel().writeAndFlush(newMsg);
Channel.write()
总是从 ChannelPipeline
的尾部开始。
ChannelHandlerContext.write()
从ChannelHandler
的当前位置开始.
当然,这也取决于您的 "protocol"(例如,如果您使用 HTTP,则 HTTP 协议不支持为同一请求发送 2 个回答)。但是假设您的协议允许您发送多个响应部分:
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不代表成功的情况。
我看过Netty Guide,它对ChannelFuture 的解释不多。我发现 ChannelFuture 在应用时是一个复杂的想法。
我想做的是在初始响应后将消息写入上下文。不同于典型的 request/response 流程。我需要这样的流程:
- 客户端发送请求->服务器(netty)
- 服务器发送响应 ctx.writeAndFlush(msg);
- 服务器在第 2 步完成后向该 ctx 发送更多消息。
问题是,如果我这样做,第二次写入不会发送出去:
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 看起来更好,但请确保测试操作是否成功。如果不是,请使用 future.getCause() 访问异常。并不是说它会改变功能,而是您可以通过直接在 write 调用的结果上直接添加侦听器来缩短代码,即您不需要声明未来本身,因为它将在回调中提供。
试试这个:
ctx.channel().writeAndFlush(response);
Message newMsg = createMessage();
ctx.channel().writeAndFlush(newMsg);
Channel.write()
总是从 ChannelPipeline
的尾部开始。
ChannelHandlerContext.write()
从ChannelHandler
的当前位置开始.
当然,这也取决于您的 "protocol"(例如,如果您使用 HTTP,则 HTTP 协议不支持为同一请求发送 2 个回答)。但是假设您的协议允许您发送多个响应部分:
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不代表成功的情况。