尝试检索 Netty 中的最后一个处理程序时间歇性地在处理程序上获取 Null
getting Null on handler intermittently when trying to retrieve last handler in Netty
我有一个连接到远程服务器以进行请求-响应的 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);
}
}
为什么处理程序间歇性地为空,正确的做法是什么? (我评论了抛出NPE的那一行)
您需要注意的一件事是,当 Netty 通道处于关闭过程中时,最后一步是删除所有处理程序,此步骤是必需的,因此所有清理例程都得到 运行 在这些处理程序中。
这意味着,通道关闭后,您将无法访问管道中的任何处理程序。
在您的代码中,您正在等待通道完全关闭的事件,这意味着之后的代码与通道关闭事件有 "happens after" 关系。
一个解决方案是制作一个自定义承诺对象,并将其传递给处理程序,然后处理程序用响应填充它:
// 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);
}
}
这个解决方案有效,因为即使通道及其属性在选择时被清除,我们仍然有对包含最终结果的承诺的引用
我有一个连接到远程服务器以进行请求-响应的 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);
}
}
为什么处理程序间歇性地为空,正确的做法是什么? (我评论了抛出NPE的那一行)
您需要注意的一件事是,当 Netty 通道处于关闭过程中时,最后一步是删除所有处理程序,此步骤是必需的,因此所有清理例程都得到 运行 在这些处理程序中。
这意味着,通道关闭后,您将无法访问管道中的任何处理程序。
在您的代码中,您正在等待通道完全关闭的事件,这意味着之后的代码与通道关闭事件有 "happens after" 关系。
一个解决方案是制作一个自定义承诺对象,并将其传递给处理程序,然后处理程序用响应填充它:
// 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);
}
}
这个解决方案有效,因为即使通道及其属性在选择时被清除,我们仍然有对包含最终结果的承诺的引用