简体   繁体   English

Netty ChannelFuture 如何运作?

[英]How Netty ChannelFuture works?

I've read Netty Guide , it does not explain much on ChannelFuture.我读过Netty Guide ,它在 ChannelFuture 上没有解释太多。 I find ChannelFuture is a complex idea when applying it.我发现 ChannelFuture 在应用时是一个复杂的想法。

What I am trying to do is to write message to a context after it's initial response.我想做的是在初始响应后将消息写入上下文。 Different from typical request/response flow.不同于典型的请求/响应流。 I need a flow like this:我需要这样的流程:

  1. Client send request -> Server (netty)客户端发送请求 -> 服务器(netty)
  2. Server send a response with ctx.writeAndFlush(msg);服务器使用 ctx.writeAndFlush(msg) 发送响应;
  3. Server send some more message to that ctx after step 2 is complete.步骤 2 完成后,服务器向该 ctx 发送更多消息。

The problem is that if I do something like this, the second write will not send out:问题是,如果我做这样的事情,第二次写不会发出:

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

Then I try to use ChannelFuture, it works, but I am not sure if I am logically correct:然后我尝试使用 ChannelFuture,它有效,但我不确定我在逻辑上是否正确:

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

or should I use a ChannelFutureListener() instead?还是应该改用 ChannelFutureListener() ?

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

Will this also works?这也行吗?

Which one is the best practice approach?哪一种是最佳实践方法? Is there any potential problem using method 2?使用方法2有什么潜在问题吗?

Of course, this depends too on your "protocol" (meaning for instance if you use HTTP, sending 2 answears for the same request is not supported by HTTP protocol).当然,这也取决于您的“协议”(例如,如果您使用 HTTP,则 HTTP 协议不支持为同一请求发送 2 个应答)。 But let say your protocol allows you to send multiple response parts:但是假设您的协议允许您发送多个响应部分:

Netty add messages to send to the pipeline, respecting the order. Netty 添加要发送到管道的消息,遵守顺序。

So in your first example, I'm a bit surprised it does not work:所以在你的第一个例子中,我有点惊讶它不起作用:

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

However it could be lead by your protocol.但是,它可能由您的协议引导。 For instance, this could happen:例如,这可能发生:

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

So if your protocol must admit that first message is sent already, then you have to wait for the first, so doing something like:因此,如果您的协议必须承认第一条消息已经发送,那么您必须等待第一条消息,因此请执行以下操作:

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
    }
  }
});

So your last proposal (I've just don't create a ChannelFuture but directly used the result of writeAndFlush, but both are equals).所以你的最后一个建议(我只是不创建 ChannelFuture 而是直接使用 writeAndFlush 的结果,但两者都是相等的)。 Just take care of the case where operationComplete does not mean it is in success.只需注意 operationComplete 并不意味着它成功的情况。

Try this:试试这个:

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

Channel.write() always starts from the tail of the ChannelPipeline . Channel.write()总是从ChannelPipeline的尾部开始。

ChannelHandlerContext.write() starts from the current position of the ChannelHandler . ChannelHandlerContext.write()从当前位置开始ChannelHandler

#2 looks better but make sure to test if the operation was successful. #2 看起来更好,但请确保测试操作是否成功。 If not, use future.getCause() to access the exception.如果没有,请使用 future.getCause() 访问异常。 Not that it will change the functionality, but you can shorten the code by simply adding the listener directly on the result of the write call, Ie you don't need to declare the future itself since it will be provided in the callback.并不是说它会改变功能,但是您可以通过简单地直接在 write 调用的结果上添加侦听器来缩短代码,即您不需要声明未来本身,因为它将在回调中提供。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM