我有一个Netty客户端,该客户端连接到远程服务器以进行请求-响应。我想阻止直到远程连接成功并解析响应。我的处理程序在检索结果方面类似于Netty factorial example。
这就是我所拥有的
Channel ch = bootstrap.connect(addr).sync().channel();
ChannelFuture f = ch.writeAndFlush(obj);
//blocking operation
ch.closeFuture().sync();
MyHandler handler = (MyHandler) f.channel().pipeline().last(); //this handler is null
String responseString = handler.responseString;
f.channel().close();
处理程序代码
MyHandler extends ChannelInboundHandlerAdapter {
public String result = null;
@Override
public void channelRead(final ChannelHandlerContext ctx, Object msg) {
if (msg instanceof FullHttpResponse) {
result = parse(msg);
}
// The following line automatically closes the channel:
ctx.channel().writeAndFlush(Unpooled.EMPTY_BUFFER).addListener(ChannelFutureListener.CLOSE);
}
}
为什么处理程序会间歇性地使null无效,正确的处理方式是什么? (我在抛出NPE的行上发表了评论)
答案 0 :(得分:2)
您需要了解的一件事是,当Netty通道处于关闭状态时,最后一步是它将所有处理程序删除,因此需要执行此步骤,因此所有清理例程都将在其中运行处理程序。
这意味着,在关闭通道之后,您将无法访问管道中的任何处理程序。
在您的代码中,您正在等待通道完全关闭的事件,这意味着之后的代码与通道关闭事件具有“后发生”关系。
一个解决方案是制作一个自定义的Promise对象,并将其传递给处理程序,然后由处理程序填充响应:
// Somewhere inside the application:
public static final AttributeKey<Promise<String>> RESPONSE = new AttributeKey("RESPONSE");
ChannelFuture chf = bootstrap.connect(addr);
Promise<String> p = chf.channel().eventLoop().newPromise();
chf.channel().attr(RESPONSE).set(p);
//blocking operation
Channel ch = chf.sync().channel();
ChannelFuture f = ch.writeAndFlush(obj);
//blocking operation
String responseString = p.get();
f.channel().close();
....
// Inside you handler
MyHandler extends ChannelInboundHandlerAdapter {
@Override
public void channelRead(final ChannelHandlerContext ctx, Object msg) {
if (msg instanceof FullHttpResponse) {
ctx.channel().attr(RESPONSE).get().setSuccess(parse(msg));
}
// The following line automatically closes the channel:
ctx.channel()
.writeAndFlush(Unpooled.EMPTY_BUFFER)
.addListener(ChannelFutureListener.CLOSE);
}
}
此解决方案有效,因为即使在选择时清除了通道及其属性,我们仍然可以引用包含最终结果的承诺