有没有办法从Netty中的channel.write()返回自定义承诺?

时间:2014-12-02 15:29:56

标签: netty

我目前正致力于实施隐私保护数据挖掘算法。对于我正在使用Netty 4.0的不同方之间的通信部分。双方之间的沟通流程如下:

         -- multiplicationMsg --> ... -- multiplicationMsg -->
   P_{1}                                                       P_{N}
         <-- multiplicationMsg -- ... <-- multiplicationMsg --

其中P_{1}是发起和控制整个计算的主方。安全多方乘法的逻辑位于Netty ChannelHandler中。还有另一种安全添加协议。

目前我使用类似this的解决方案,由Netty核心团队的Norman Maurer展示,以便在子协议计算完成时获得通知。但这感觉有点像与框架作斗争。

有没有办法从channel.write(msg)获得自定义承诺,这将在ChannelPipeline中创建并实现?在上面的示例中,当multiplicationMsg返回P_{1}时,应该会完成此操作。

修改1

这是我通常从ChannelPipeline

之外写一条消息的行为
ChannelFuture f = channel.write(msg);
future.addListener(new ChannelFutureListener() {
    public void operationComplete(ChannelFuture future) {
         //do something with the future
    }
});

如果数据可以写入套接字或发生故障,则上述示例中的ChannelFuture f将得到满足。但除了Future之外,我还需要一种方法来取回自定义ChannelFuture,不知怎的样:

ChannelFuture f = channel.write(msg);
future.addListener(new ChannelFutureListener() {
    public void operationComplete(ChannelFuture future) {
         // I need something like the following
         if(future.isSuccess()) {
             Future myFuture = future.getMyFuture();
         }
    }
});

1 个答案:

答案 0 :(得分:4)

有很多方法可以做到这一点,这里有一个建立在netty之上的例子:

从管道外部,使用包含IoClient(来自连接初始化)的类(例如,ChannelFuture)中的公共方法发送消息。该方法看起来像这样:

public MyCustomFuture send(String msg) {
  MyCustomFuture responseFuture = new MyCustomFuture();

  channelFuture.channel().pipeline().get(MyAppClientHandler.class).setResponseFuture(responseFuture);
  channelFuture.channel().writeAndFlush(msg);   

  return responseFuture;
}

MyCustomFuture是我们创建实现netty的Future接口的自定义类,因此它的实例将代理我们的消息。 MyAppClientHandler是要履行承诺的网络管道(在responseFuture中),.setResponseFuture(...)将代理添加到管道。

根据频道的初始化,channelFuture.channel()可能仍为null,为我们提供NullPointerException。所以我们需要更改上面的代码以从回调中插入代理:

public MyCustomFuture send(final String msg) {
  final MyCustomFuture responseFuture = new MyCustomFuture();

  channelFuture.addListener(new GenericFutureListener<ChannelFuture>() {
    @Override
    public void operationComplete(ChannelFuture future) throws Exception {
      channelFuture.channel().pipeline()
          .get(MyAppClientHandler.class).setResponseFuture(responseFuture);
      channelFuture.channel().writeAndFlush(msg);                               
    }
  });

  return responseFuture;
}

关于MyCustomFuture的另一件事是它需要一个setter方法:

public void set(String msg) throws InterruptedException {
  if (state == State.DONE) {
    return;
  }
  blockingReplyHolder.put(msg);
  state = State.DONE;
}
顾名思义,

blockingReplyHolder是实现的字段,它包含履行承诺的消息,并且如果它仍然不存在则阻止(检查Future)< / p>

右。现在,当预期的消息到达管道MyAppClientHandler时,我们可以履行承诺,如:

protected void channelRead(ChannelHandlerContext ctx, String msg) throws Exception {
    responseFuture.set(msg);
}

生成的自定义API的用法是:

MyCustomFuture future = ioClient.send(message);
// do other stuff if needed
String response = future.get(); // waits if necessary
// make use of the response

这个答案来自于我正在玩弄的example